Com os tipos condicionais, um recurso poderoso do TypeScript, é possível criar tipos que dependem de outros tipos. Os tipos condicionais são avaliados em tempo de compilação e são definidos usando um operador ternário que especifica uma condição, e o ponto de interrogação indica que o tipo é condicional.
A sintaxe para um tipo condicional é a seguinte:
T extends U ? X : Y
Aqui, T
e U
são tipos, X
e Y
são tipos ou expressões de tipo, e extends
é uma palavra-chave que especifica uma restrição em T
.
Um caso de uso comum para tipos condicionais é extrair propriedades de objetos. Por exemplo, considere a seguinte interface:
interface User {
id: number;
name: string;
email: string;
}
Podemos criar um tipo que extrai as chaves de User
da seguinte forma:
type UserKeys = keyof User; // "id" | "name" | "email"
Usando um tipo condicional, podemos criar uma versão mais flexível de UserKeys
que pode extrair chaves de qualquer tipo de objeto:
type KeysOfType<T, U> = {
[K in keyof T]: T[K] extends U ? K : never;
}[keyof T];
Aqui, KeysOfType
recebe dois parâmetros de tipo, T
e U
, e retorna uma união de chaves de T
cujos valores são do tipo U
. Por exemplo:
interface Car {
make: string;
model: string;
year: number;
}
type StringKeys = KeysOfType<Car, string>; // "make" | "model"
Esse tipo retorna "make" e "model", pois essas são as chaves de Car cujos valores são do tipo string
.
Outro caso de uso para tipos condicionais é verificar se um tipo é um array. O TypeScript fornece um tipo Array
integrado, mas às vezes precisamos verificar se um valor é um array em tempo de execução. Podemos criar um tipo que verifica se um tipo é um array da seguinte forma:
type IsArray<T> = T extends any[] ? true : false;
Aqui, IsArray
recebe um parâmetro de tipo T
e retorna um booleano indicando se T
é um tipo de array. Por exemplo:
type A = IsArray<number[]>; // true
type B = IsArray<string>; // false
Os tipos condicionais também suportam a palavra-chave infer
, que nos permite inferir um tipo de outro tipo. Por exemplo, considere o seguinte tipo:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
Aqui, ReturnType recebe um tipo de função T
e retorna o tipo de retorno de T
. Por exemplo:
function add(a: number, b: number): number {
return a + b;
}
type Result = ReturnType<typeof add>; // number
Este tipo retorna number
, pois esse é o tipo de retorno da função add
.
Além disso, a página aborda como combinar tipos condicionais com outros recursos do TypeScript, como tipos genéricos e uniões de tipos. Por exemplo, podemos criar um tipo que verifica se um tipo é uma união de tipos de objeto da seguinte forma:
type IsObjectUnion<T> = T extends object ? T[keyof T] : never;
type ExampleUnion = { a: string } | { b: number };
type Result = IsObjectUnion<ExampleUnion>; // string | number
Este tipo retorna string | number
, pois ExampleUnion
é uma união de tipos de objeto que contém a: string
e b: number
.
Conclusão
Os tipos condicionais são uma ferramenta poderosa do TypeScript para tipos mais flexíveis e precisos. Com os tipos condicionais, é possível extrair propriedades de objetos, verificar se um tipo é um array e inferir tipos de outros tipos, além de combinar tipos condicionais com outros recursos do TypeScript para criar tipos mais complexos e úteis.
Referências
Documentação oficial: https://www.typescriptlang.org/
Créditos da imagem: https://brandontle.com/writing/why-typescript/
Introdução prática: https://auth0.com/blog/working-with-typeScript-a-practical-introduction/
Top comments (2)
Nice artigo, generic type é uma parada maravilhosa demais quando estamos em cenários não muito padronizados 💪🏻
Só um ponto, se você quiser em seus code blocks você pode especificar o tipo após abrir-lo, tipo:
Apenas um toque, ta 😅
@renancferro muitissimo obrigada pela dica! Também o meu obrigada pelo feedback, significa muito para mim como profissional na área. Todas as revisões, atualizações e melhorias são muito bem-vindas! Grata! 🤩