Typescript e sua palavra-chave "type"
Tags: typescript, types, literals, keyword
Published: 2022-05-01 04:21:30

Não é novidade que o Typescript é um _superset_ que veio para trazer conceitos de Orientação a Objeto para a linguagem Javascript. Contudo, algumas palavras-chave dessa linguagem criada pela Microsoft ainda geram dúvidas.

Além da modelagem de entidades e objetos de valor por meio de classes, também é possível realizar tal modelagem utilizando uma _interface_ ou um _type_. Abaixo estão um exemplo de modelagem usando cada recurso da linguagem.

```ts
class People {
    name: string;
    age: number;
}

interface People {
    name: string;
    age: number;
}

type People = {
    name: string;
    age: number;
}
```

Neste momento você deve estar pensando: _"Se é possível realizar a modelagem de qualquer uma das três maneiras, por que eu deveria utilizar ou entender sobre o type?"_. A resposta é simples, há usos que só o uso do recurso type possibilita, abaixo discorro mais sobre cada um desses cenários.

## Type aliases
Como nome indica, é possível apelidar, isto é, dar um _alias_ a um tipo já existente, seja ele declarado como classe, interface, outro type ou de tipo primitivo.
```ts
type Student = People;

type Guid = string;
```

No exemplo acima, criamos um tipo chamado "Estudante" que, basicamente, é um apelido para o modelo "Pessoa". Também criamos um tipo para um identificador único, mapeado sobre o tipo string, já que não temos um tipo Guid (como o C# possui) em Typescript.

Apelidar um tipo existente, sobretudo tipos primitivos, é útil para trazer semântica de acordo com o contexto com que aquele tipo será usado. Um identificador do tipo string é amplo, não traz pistas sobre o formato do ID, diferentemente de um tipo GUID, que já traz no nome seu formato.

## Template literals

Esse é o recurso ideal para apelidar um ou mais valores estáticos que sejam enumeráveis. Não entendeu? Bora para um exemplo.

```ts
type MonthNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
```

Acima estão listados os índices para cada mês do ano. A vantagem de usar tipos literais é ser avisado quando um valor incorreto, isto é, que não pertence ao conjunto definido, for utilizado, como mostra o exemplo abaixo:
![Exemplo de erro ao tentar atribuir o valor 13 como número válido para um índice de um mês do ano](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yk32n0sjciqorbj3lj5m.png)

## Union types

Em resumo, é possível declarar um tipo que aceite múltiplos outros tipos (primitivos, classe, interface, _type_, literal), ou seja, um tipo que una outros tipos.

Abaixo criamos um tipo ID que aceita tanto valores do tipo string (caso seja um GUID, por exemplo) quanto do tipo number (caso seja um inteiro auto-incremental, por exemplo).
```ts
type ID = string | number;

const peopleId: ID = 13;

const postId: ID = '08288a85-b79b-4022-a0dd-1563bd0f5de1';
```

## Intersection types

Além de permitir aceitar múltiplos tipos como válido para um novo, também é possível **unir** vários tipos, isso mesmo, criar um tipo que seja a fusão de propriedades de outros dois ou mais. Este cenário de uso é restrito a declaração de entidades, **não se aplica a valores primitivos**.

No exemplo abaixo criamos uma entidade (Pessoa) e um objeto de valor (Endereço). Com o operador "**&**" conseguimos unificar os dois tipos em um novo, uma entidade para representar uma pessoa com endereço. Esse terceiro tipo conterá todos os atributos dos dois que lhe originaram.

```ts
class People {
    name: string;
    age: number;
    id: ID;
}

interface Address {
    country: string;
    city: string;
}

type PeopleWithAddress = People & Address;

const george: PeopleWithAddress = {
    age: 19,
    city: 'Serra',
    country: 'BR',
    id: 25,
    name: 'George',
    zipCode: 251475899
};
```

## Considerações finais

Com esses recursos não há mais desculpas para deixar constantes espalhadas como strings ou numbers espalhados pelo código, ou para repetir todas propriedades de um modelo em outro. É possível ter validação de valores em tempo de desenvolvimento e economizar linhas de declaração de modelo :)

References:
[Types aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases)
[Literal types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types)
[Union types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types)
[Intersection types]
(https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces)