Experts in Angular

Ahead-of-time (AOT)AOT – Phase 3: Template type checking
Template Type Checking: O Selo de Qualidade da sua Nave Angular

AOT – Phase 3: Template type checking

Na terceira e última fase da compilação AOT, o Angular CLI se transforma em um guardião vigilante, examinando cada expressão e binding dentro dos seus templates para garantir que estejam em conformidade com os tipos definidos no seu código TypeScript. Essa verificação de tipos de template é como um escudo de segurança, protegendo sua aplicação de erros em tempo de execução e proporcionando uma experiência de usuário mais estável e confiável.

Importância da Verificação de Tipos em Templates

Uma das características mais úteis do compilador Angular é a capacidade de verificar as expressões de binding nos templates e identificar erros de tipo que podem causar problemas na execução do aplicativo. Ao detectar esses erros na fase de compilação, os desenvolvedores podem corrigir problemas de tipo de maneira proativa, garantindo que o aplicativo funcione como esperado quando for entregue aos usuários.

Habilitando a Verificação de Tipos

Para ativar esta fase, adicione a opção do compilador "fullTemplateTypeCheck": true em "angularCompilerOptions" no arquivo de configuração do TypeScript do projeto (tsconfig.json). Esta opção garante que o compilador verifique detalhadamente as expressões de binding nos templates.

{
  "compilerOptions": {
    ...
  },
  "angularCompilerOptions": {
    "fullTemplateTypeCheck": true
  }
}
Exemplo de Verificação de Tipos

Considere o seguinte componente:

@Component({
  selector: 'my-component',
  template: '{{person.addresss.street}}'
})
class MyComponent {
  person?: Person;
}

Ao compilar este componente com a verificação de tipos habilitada, o seguinte erro será gerado:

my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'?

Neste exemplo, o erro está na expressão {{person.addresss.street}}, onde addresss é um erro de digitação para address. O compilador gera uma mensagem de erro indicando que a propriedade addresss não existe no tipo Person e sugere a correção.

Arquivo Sintético e Localização do Erro

A mensagem de erro refere-se a um arquivo sintético, como my.component.ts.MyComponent.html, gerado pelo compilador para armazenar o conteúdo do template da classe MyComponent. Este arquivo nunca é gravado em disco, mas é usado para representar o conteúdo do template durante a verificação de tipos. As informações de linha e coluna na mensagem de erro são relativas à string de template na anotação @Component.

Se um componente utiliza templateUrl em vez de template, os erros são relatados no arquivo HTML referenciado por templateUrl.

Relatórios Detalhados de Erros

A localização do erro nas mensagens de erro é no início do nó de texto que contém a expressão de interpolação com o erro. Se o erro estiver em um binding de atributo, como [value]="person.address.street", a localização do erro é o próprio atributo que contém a expressão incorreta.

A validação utiliza o verificador de tipos do TypeScript e as opções fornecidas ao compilador para controlar o quão detalhada será a verificação de tipos. Por exemplo, se a opção strictTypeChecks estiver especificada, erros adicionais, como Object is possibly 'undefined', também serão relatados:

my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'
Uma Aplicação Angular Segura e Confiável

Uma Aplicação Angular Segura e Confiável

A verificação de tipos de template é uma ferramenta essencial para garantir a qualidade e a robustez das suas aplicações Angular. Ao habilitar essa funcionalidade e seguir as melhores práticas de tipagem, você estará construindo um escudo de segurança que protege sua nave espacial de erros em tempo de execução, proporcionando uma experiência de usuário impecável e livre de falhas.

github.com/gitnacho/angularSujeito à licença (MIT)

Refinamento de Tipos (Type Narrowing): Navegando com Precisão entre Tipos em Templates

No universo Angular, a flexibilidade dos tipos de dados é uma ferramenta poderosa, mas também pode ser um desafio para o verificador de tipos de template. Em algumas situações, você pode precisar lidar com uniões de tipos (union types), onde uma variável pode ter diferentes tipos possíveis. Para garantir a segurança e a precisão da verificação de tipos nesses casos, o Angular CLI oferece um mecanismo de refinamento de tipos (type narrowing) que permite restringir o tipo de uma variável com base em condições específicas.

O Poder do *ngIf

A diretiva *ngIf não apenas controla a renderização condicional de elementos no template, mas também atua como um filtro de tipos, refinando o tipo de uma variável com base na condição especificada. Imagine o *ngIf como um sistema de navegação inteligente que guia sua nave espacial Angular por diferentes rotas, garantindo que ela chegue ao destino correto.

Vamos revisitar o exemplo anterior, onde a propriedade person pode ser undefined:

@Component({
  selector: 'my-component',
  template: '{{person.address.street}}' 
})
class MyComponent {
  person?: Person; 
}

Para evitar o erro de tipo “Object is possibly ‘undefined'”, podemos utilizar o *ngIf para garantir que a expressão de binding só seja avaliada quando person tiver um valor definido:

@Component({
  selector: 'my-component',
  template: '<span *ngIf="person"> {{person.address.street}} </span>' 
})
class MyComponent {
  person?: Person; 
}

Agora, o compilador TypeScript pode inferir que a variável person dentro do *ngIf nunca será undefined, permitindo que a expressão person.address.street seja verificada com segurança.

Outros Mecanismos de Refinamento de Tipos

Além do *ngIf, o Angular CLI também suporta outros mecanismos de refinamento de tipos em templates, como:

  • Operador de navegação segura (?.): Permite acessar propriedades de objetos potencialmente nulos de forma segura, evitando erros em tempo de execução.
  • Guards de tipo em diretivas personalizadas: Você pode criar suas próprias diretivas que refinam o tipo de uma variável com base em condições específicas.

O refinamento de tipos é uma ferramenta essencial para lidar com uniões de tipos e garantir a precisão da verificação de tipos em seus templates Angular. Ao utilizar o *ngIf, o operador de navegação segura e outras técnicas de refinamento, você estará construindo aplicações mais robustas e confiáveis, evitando erros em tempo de execução e proporcionando uma experiência de usuário impecável.

O Operador de Asserção de Não Nulo

O operador de asserção de não nulo (!) é uma ferramenta poderosa no TypeScript e Angular, projetada para suprimir erros do tipo Object is possibly 'undefined'. Esse operador é particularmente útil em situações onde o uso de *ngIf é inconveniente ou quando há uma restrição no componente que garante que a expressão nunca será null ou undefined no momento da interpolação da expressão de binding.

Quando Usar o Operador de Asserção de Não Nulo

O operador de asserção de não nulo é útil em cenários onde há garantias lógicas no código que não podem ser facilmente representadas no sistema de tipos do TypeScript. Vamos explorar um exemplo para entender melhor:

@Component({
  selector: 'my-component',
  template: '<span *ngIf="person"> {{person.name}} lives on {{address!.street}} </span>'
})
class MyComponent {
  person?: Person;
  address?: Address;

  setData(person: Person, address: Address) {
    this.person = person;
    this.address = address;
  }
}
Análise do Exemplo

Neste exemplo, os objetos person e address são sempre definidos juntos através do método setData. Isso implica que, se person estiver definido, address também estará. No entanto, essa lógica não é automaticamente aparente para o TypeScript, resultando em um erro de potencial undefined.

Ao usar address!.street, estamos dizendo ao compilador que estamos certos de que address não é undefined naquele contexto, suprimindo o erro. É importante notar que, enquanto o operador de asserção de não nulo pode resolver problemas imediatos, ele deve ser usado com cuidado, pois alterações futuras no código podem invalidar essa garantia implícita.

Melhores Práticas

Embora o operador de asserção de não nulo possa ser uma solução rápida, é geralmente mais seguro e mais claro incluir verificações explícitas, como mostrado na solução aprimorada abaixo:

@Component({
  selector: 'my-component',
  template: '<span *ngIf="person && address"> {{person.name}} lives on {{address.street}} </span>'
})
class MyComponent {
  person?: Person;
  address?: Address;

  setData(person: Person, address: Address) {
    this.person = person;
    this.address = address;
  }
}
Por Que Esta Abordagem é Melhor?
  1. Robustez do Código: Ao garantir explicitamente que tanto person quanto address são não nulos com *ngIf, você protege seu código contra mudanças futuras que possam quebrar as garantias implícitas que o operador de não nulo faz.
  2. Legibilidade e Manutenção: Quem ler o código no futuro verá imediatamente que há uma dependência entre person e address, facilitando a compreensão e manutenção do código.
  3. Prevenção de Erros: Eliminar o uso de ! sempre que possível ajuda a evitar erros difíceis de detectar, que podem ocorrer quando suposições sobre o estado dos dados mudam sem que o código seja atualizado para refletir essas mudanças.

O operador de asserção de não nulo é uma ferramenta útil, mas deve ser usado com cautela. Em muitos casos, uma verificação explícita no template com *ngIf pode fornecer um código mais seguro e sustentável. Quando usado corretamente, o operador de não nulo pode resolver problemas específicos e fornecer garantias de tipos onde o sistema de tipos do TypeScript não pode. No entanto, é importante avaliar cuidadosamente a lógica e as garantias que você está assumindo ao usá-lo.


Na terceira e última fase da compilação AOT, o Angular CLI assume o papel de um inspetor de qualidade rigoroso, examinando cada detalhe dos seus templates para garantir que estejam em conformidade com os tipos definidos no seu código TypeScript. Essa verificação de tipos de template é a última etapa antes do lançamento da sua nave espacial Angular, garantindo que ela esteja livre de erros e pronta para explorar o universo da web com segurança e confiabilidade.

Ao longo desta jornada, exploramos os diferentes modos de verificação de tipos, desde o básico até o estrito, e como eles afetam a análise dos seus templates. Aprendemos a lidar com uniões de tipos usando o refinamento de tipos e o operador de asserção não nula, e vimos como garantir a compatibilidade dos dados em bindings de entrada.

Com o Template Type Checking, você tem em mãos uma ferramenta poderosa para detectar e corrigir erros em tempo de compilação, evitando problemas em tempo de execução e proporcionando uma experiência de usuário impecável. Ao dominar essa ferramenta e seguir as melhores práticas de tipagem, você estará construindo aplicações Angular mais robustas, escaláveis e fáceis de manter.