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! 🤩