Tabemos as principais características do TypeScript Type System quando discutimos Por que TypeScript? A seguir estão alguns pontos chave dessa discussão que não precisam de mais explicações:
-
O sistema de tipo em TypeScript foi projetado para ser opcional para que o seu JavaScript seja TypeScript.
-
O TypeScript não bloqueia a emissão de JavaScript na presença de erros de tipo, permitindo-lhe actualizar progressivamente o seu JS para TS.
Agora vamos começar com a sintaxe do sistema de tipo TypeScript. Desta forma você pode começar a usar estas anotações no seu código imediatamente e ver o benefício. Isto irá prepará-lo para um mergulho mais profundo mais tarde.
Como mencionado antes Tipos são anotados usando a sintaxe :TypeAnnotation
. Qualquer coisa que esteja disponível no espaço de declaração de tipo pode ser usada como uma Anotação de Tipo.
O exemplo seguinte demonstra anotações de tipo para variáveis, parâmetros de função e valores de retorno de função:
var num: number = 123;function identity(num: number): number {return num;}
Tipos Primitivos
Os tipos primitivos JavaScript estão bem representados no sistema de tipo TypeScript. Isto significa string
, number
, boolean
como demonstrado abaixo:
var num: number;var str: string;var bool: boolean;num = 123;num = 123.456;num = '123'; // Errorstr = '123';str = 123; // Errorbool = true;bool = false;bool = 'false'; // Error
Arrays
TypeScript fornece sintaxe de tipo dedicada para arrays para facilitar a anotação e documentação do seu código. A sintaxe é basicamente a pós-fixação a qualquer anotação de tipo válida (por exemplo,
:boolean
). Ela permite que você faça com segurança qualquer manipulação de array que você normalmente faria e o protege de erros como a atribuição de um membro do tipo errado. Isto é demonstrado abaixo:
var boolArray: boolean;boolArray = ;console.log(boolArray); // trueconsole.log(boolArray.length); // 2boolArray = true;boolArray = ;boolArray = 'false'; // Error!boolArray = 'false'; // Error!boolArray = ; // Error!
Interfaces
Interfaces são a forma principal no TypeScript para compor múltiplas anotações de tipo em uma única anotação nomeada. Considere o seguinte exemplo:
interface Name {first: string;second: string;}var name: Name;name = {first: 'John',second: 'Doe'};name = { // Error : `second` is missingfirst: 'John'};name = { // Error : `second` is the wrong typefirst: 'John',second: 1337};
Aqui compusemos as anotações first: string
+ second: string
em uma nova anotação Name
que reforça as verificações de tipo em membros individuais. As interfaces têm muito poder no TypeScript e nós vamos dedicar uma seção inteira a como você pode usar isso em seu benefício.
Anotação Tipo Inline
Em vez de criar uma nova interface
você pode anotar o que quiser na linha usando :{ /*Structure*/ }
. O exemplo anterior apresentado novamente com um tipo inline:
var name: {first: string;second: string;};name = {first: 'John',second: 'Doe'};name = { // Error : `second` is missingfirst: 'John'};name = { // Error : `second` is the wrong typefirst: 'John',second: 1337};
Os tipos inline são ótimos para fornecer rapidamente uma anotação de um tipo inline para algo. Isso poupa-lhe o incómodo de encontrar um nome de tipo (potencialmente mau). Entretanto, se você se encontrar colocando o mesmo tipo de anotação em linha várias vezes, é uma boa idéia considerar refatorá-la em uma interface (ou um type alias
coberto mais tarde nesta seção).
Tipos Especiais
Além dos tipos primitivos que foram cobertos há alguns tipos que têm um significado especial no TypeScript. Estes são any
, null
, undefined
, void
.
qualquer
O tipo any
ocupa um lugar especial no sistema de tipo TypeScript. Ele lhe dá uma escotilha de escape do sistema de tipo para avisar o compilador para se desligar. any
é compatível com qualquer e todos os tipos no sistema de tipo. Isto significa que qualquer coisa pode ser atribuída a ele e pode ser atribuída a qualquer coisa. Isto é demonstrado no exemplo abaixo:
var power: any;// Takes any and all typespower = '123';power = 123;// Is compatible with all typesvar num: number;power = num;num = power;
Se você está portando código JavaScript para TypeScript, você vai ser amigo íntimo de any
no início. No entanto, não leve essa amizade muito a sério, pois isso significa que cabe a você garantir a segurança do tipo. Você está basicamente a dizer ao compilador para não fazer nenhuma análise estática significativa.
nulo e indefinido
Como eles são tratados pelo sistema de tipo depende da bandeira strictNullChecks
do compilador (nós cobrimos esta bandeira mais tarde). Quando em strictNullCheck:false
, os caracteres null
e undefined
JavaScript são efetivamente tratados pelo sistema de tipo o mesmo que algo do tipo any
. Estes literais podem ser atribuídos a qualquer outro tipo. Isto é demonstrado no exemplo abaixo:
var num: number;var str: string;// These literals can be assigned to anythingnum = null;str = undefined;
:void
Utilizar :void
para significar que uma função não tem um tipo de retorno:
function log(message): void {console.log(message);}
Generics
Muitos algoritmos e estruturas de dados em informática não dependem do tipo real do objeto. No entanto, o usuário ainda deseja impor uma restrição entre várias variáveis. Um exemplo simples de brinquedo é uma função que pega uma lista de itens e retorna uma lista invertida de itens. A restrição aqui é entre o que é passado para a função e o que é retornado pela função:
function reverse<T>(items: T): T {var toreturn = ;for (let i = items.length - 1; i >= 0; i--) {toreturn.push(items);}return toreturn;}var sample = ;var reversed = reverse(sample);console.log(reversed); // 3,2,1// Safety!reversed = '1'; // Error!reversed = ; // Error!reversed = 1; // Okayreversed = ; // Okay
Aqui você está basicamente dizendo que a função reverse
toma um array (items: T
) de algum tipo T
(observe o parâmetro de tipo em reverse<T>
) e retorna um array de tipo T
(observe : T
). Como a função reverse
devolve itens do mesmo tipo, TypeScript sabe que a variável reversed
também é do tipo number
e lhe dará segurança ao Type. Similarmente se você passar em um array de string
para a função reversa o resultado retornado também é um array de string
e você obtém segurança do tipo similar como mostrado abaixo:
var strArr = ;var reversedStrs = reverse(strArr);reversedStrs = ; // Error!
De fato, arrays JavaScript já têm uma função .reverse
e TypeScript de fato usa genéricos para definir sua estrutura:
interface Array<T> {reverse(): T;// ...}
Isto significa que você obtém segurança de digitação ao chamar .reverse
em qualquer array como mostrado abaixo:
var numArr = ;var reversedNums = numArr.reverse();reversedNums = ; // Error!
Discutiremos mais tarde sobre a interface Array<T>
quando apresentarmos lib.d.ts
na seção Declarações Ambientais.
Tipo de União
Bastante comumente em JavaScript você quer permitir que uma propriedade seja de múltiplos tipos, por exemplo, um string
ou um number
. É aqui que o tipo de união (indicado por |
numa anotação de tipo, por exemplo, string|number
) vem a calhar. Um caso de uso comum é uma função que pode pegar um único objeto ou um array do objeto e.g.:
function formatCommandline(command: string|string) {var line = '';if (typeof command === 'string') {line = command.trim();} else {line = command.join(' ').trim();}// Do stuff with line: string}
Tipo de Intersecção
extend
é um padrão muito comum em JavaScript onde você pega dois objetos e cria um novo que tem as características de ambos os objetos. Um Tipo de Intersecção permite-lhe usar este padrão de uma forma segura como demonstrado abaixo:
function extend<T, U>(first: T, second: U): T & U {return { ...first, ...second };}const x = extend({ a: "hello" }, { b: 42 });// x now has both `a` and `b`const a = x.a;const b = x.b;
Tuple Type
JavaScript não tem suporte de tuple de primeira classe. As pessoas geralmente usam apenas um array como um tuple. Isto é exatamente o que o sistema tipo TypeScript suporta. Tuples pode ser anotado usando :
etc. Um tuple pode ter qualquer número de membros. Tuples são demonstrados no exemplo abaixo:
var nameNumber: ;// OkaynameNumber = ;// Error!nameNumber = ;
Combine isto com o suporte a desestruturação em TypeScript, tuples sentem-se razoavelmente de primeira classe apesar de serem arrays por baixo:
var nameNumber: ;nameNumber = ;var = nameNumber;
Type Alias
TypeScript fornece uma sintaxe conveniente para fornecer nomes para anotações de tipo que você gostaria de usar em mais de um lugar. Os alias são criados usando a sintaxe type SomeName = someValidTypeAnnotation
. Um exemplo é demonstrado abaixo:
type StrOrNum = string|number;// Usage: just like any other notationvar sample: StrOrNum;sample = 123;sample = '123';// Just checkingsample = true; // Error!
Unlike an interface
você pode dar um alias de tipo para literalmente qualquer tipo de anotação (útil para coisas como tipos de união e intersecção). Aqui estão mais alguns exemplos para familiarizá-lo com a sintaxe:
type Text = string | { text: string };type Coordinates = ;type Callback = (data: string) => void;
TIP: Se você precisa ter hierarquias de anotações de tipo use um
interface
. Elas podem ser usadas comimplements
eextends
TIP: Use um tipo alias para estruturas de objetos mais simples (como
Coordinates
) apenas para dar-lhes um nome semântico. Também quando você quer dar nomes semânticos aos tipos Union ou Intersection, um alias Type é o caminho a seguir.
Summary
Agora que você pode começar a anotar a maior parte do seu código JavaScript, podemos saltar para os detalhes de toda a potência disponível no TypeScript’s Type System.