O TypeScript tem a capacidade de definir classes como abstratas. Isso significa que eles não podem ser instanciados diretamente; apenas subclasses não abstratas podem ser. Vamos dar uma olhada no que isso significa quando se trata do uso do construtor.
Fazendo um scratchpad
Para aprofundar isso, vamos criar um projeto de scratchpad para trabalhar. Vamos criar um projeto Node.js e instalar TypeScript como uma dependência.
mkdir ts-abstract-constructors cd ts-abstract-constructors npm init–yes npm install typescript @ types/node–save-dev
Agora temos um arquivo package.json configuração. Precisamos inicializar um projeto TypeScript também:
npx tsc–init
Isso nos dará um arquivo tsconfig.json que conduzirá a configuração do TypeScript. Por padrão, o TypeScript transpila para uma versão mais antiga do JavaScript anterior às classes. Portanto, vamos atualizar a configuração para atingir uma versão mais recente da linguagem que os inclui:
“target”:”es2020″,”lib”: [“es2020”],
Vamos criar um arquivo TypeScript chamado index.ts. O nome não é significativo; precisamos apenas de um arquivo para desenvolver.
Finalmente, adicionaremos um script ao nosso package.json que compila nosso TypeScript para JavaScript e, em seguida, executa o JS com o nó:
“start”:”tsc–project \”. \”&& node index.js”
Fazendo uma classe abstrata em TypeScript
Agora estamos prontos. Vamos adicionar uma classe abstrata com um construtor ao nosso arquivo index.ts:
classe abstrata ViewModel {id: string; construtor (id: string) {this.id=id; }}
Considere a classe ViewModel acima. Digamos que estejamos construindo algum tipo de aplicativo CRUD; teremos visões diferentes. Cada visualização terá um modelo de visualização correspondente, que é uma subclasse da classe abstrata ViewModel.
A classe ViewModel tem um parâmetro de id obrigatório no construtor. Isso é para garantir que cada viewmodel tenha um valor de id. Se este fosse um aplicativo real, id provavelmente seria o valor com o qual uma entidade foi pesquisada em algum tipo de banco de dados.
É importante ressaltar que todas as subclasses de ViewModel devem:
Não implementar um construtor de qualquer forma, deixando o construtor da classe base para se tornar o construtor padrão da subclasse Implemente seu próprio construtor que invoca o construtor da classe base ViewModel
Fazendo nossa classe abstrata para uma rodada
Agora vamos ver o que podemos fazer com nossa classe abstrata.
Em primeiro lugar, podemos instanciar nossa classe abstrata? Não devemos ser capazes de fazer isso:
const viewModel=new ViewModel (‘my-id’); console.log (`o id é: $ {viewModel.id}`);
Com certeza, a execução de npm start resulta no seguinte erro (que também está sendo relatado por nosso editor, VS Code).
index.ts: 9: 19-erro TS2511: Não é possível criar uma instância de um resumo aula. const viewModel=new ViewModel (‘my-id’);
Tremendo. No entanto, é importante lembrar que abstrato é um conceito do TypeScript. Quando compilamos nosso TS, embora esteja gerando um erro de compilação, ele ainda transpila um arquivo index.js que se parece com este:
“use strict”; classe ViewModel {construtor (id) {this.id=id; }} const viewModel=new ViewModel (‘my-id’); console.log (`o id é: $ {viewModel.id}`);
Como podemos ver, não há menção de resumo; é apenas uma aula simples. Na verdade, se executarmos diretamente o arquivo com o nó index.js, podemos ver uma saída de:
o id é: my-id
Portanto, o código transpilado é JavaScript válido, mesmo se o código-fonte não for TypeScript válido. Tudo isso nos lembra que o abstrato é uma construção TypeScript.
Subclassificação sem um novo construtor
Vamos agora criar nossa primeira subclasse de ViewModel e tentar instanciá-la:
classe NoNewConstructorViewModel extends ViewModel {}//erro TS2554: esperado 1 argumento, mas obteve 0. const viewModel1=new NoNewConstructorViewModel (); const viewModel2=new NoNewConstructorViewModel (‘my-id’);
Como o compilador TypeScript nos diz, a segunda dessas instanciações é legítima porque depende de o construtor da classe base. O primeiro não é porque não existe um construtor sem parâmetros.
Subclassificando com um novo construtor
Feito isso, vamos tentar criar uma subclasse e implementar um novo construtor que tem dois parâmetros (para diferenciar de o construtor que estamos substituindo):
class NewConstructorViewModel extends ViewModel {data: string; construtor (id: string, dados: string) {super (id); this.data=data; }}//erro TS2554: Esperados 2 argumentos, mas obteve 0. const viewModel3=new NewConstructorViewModel ();//erro TS2554: Esperados 2 argumentos, mas obteve 1. const viewModel4=new NewConstructorViewModel (‘my-id’); const viewModel5=new NewConstructorViewModel (‘my-id’,’informações importantes’);
Novamente, apenas uma das instanciações tentadas é legítima. viewModel3 não é porque não existe um construtor sem parâmetros. viewModel4 não é porque substituímos o construtor da classe base pelo nosso novo, que tem dois parâmetros. Portanto, viewModel5 é a nossa instanciação”Cachinhos Dourados”-é perfeita!
Também é importante notar que estamos chamando super no construtor NewConstructorViewModel. Isso invoca o construtor da classe base ViewModel (ou “super”). O TypeScript exige que passemos os argumentos apropriados (no nosso caso, uma única string).
Conclusão
Vimos que o TypeScript garante o uso correto de construtores quando temos uma classe abstrata. É importante ressaltar que todas as subclasses de classes abstratas:
Não implemente um construtor, deixando o construtor da classe base (o construtor abstrato) para se tornar o construtor padrão da subclasse Implementar seu próprio construtor, que invoca a base (ou “Super”) construtor de classe com os argumentos corretos