Learn TypeScript Help

Inferring Additional Types in Conditions

Pode existir uma tensão entre a necessidade para aceitar um intervalo mais amplos de tipos por meio de um parametro de tipo generico e a necessidade de conhecer os detalhes desses tipos. Como no exemplo abaixo, mostra uma função que aceita um array ou um único objeto de um determinado tipo:

import {City, Person, Product, Employee} from "./dataTypes"; function getValue<T, P extends keyof T>(data: T, propName: P): T[P] { if (Array.isArray(data)) { return data[0][propName]; } else { return data[propName]; } } let products = [new Product("Kayak", 275), new Product("Lifejacket", 48.95)]; console.log(`Array Value: ${getValue(products, "price")}`); console.log(`Single Total: ${getValue(products[0], "price")}`);

Esse código não vai compilar porque o generic parameter não está corretamente capturando o relacionamento entre os tipos. Se a função total recebe um array do parametro data e retorna o valor da propriedade especifica pelo valor do propName para esse objeto. O parametro propName é restringido usando keyof que é um problema quando um array é usado porque keyof retorna uma união dos nomes das propriedades definidos pelo objeto array do JS e não as propriedades do tipo contido no array que pode ser visto essa mensagem de erro de compilação:

src/index.ts(12,48): error TS2345: Argument of type '"price"' is not assignable to parameter of type 'number | "length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | ... 14 more ... | "includes"' .

O TS tem a keyword infer podem ser usado para inferir tipos que não são explicitamente expressas nos parametros do conditional type. Para o exemplo, isso significa que significa que podemos perguntar ao compilador para inferir os tipos de objetos no array, como mostrado abaixo:

import {City, Person, Product, Employee} from "./dataTypes"; type targetKeys<T> = T extends (infer U)[] ? keyof U : keyof T; function getValue<T, P extends targetKeys<T>>(data: T, propName: P): T[P] { if (Array.isArray(data)) { return data[0][propName]; } else { return data[propName]; } } let products = [new Product("Kayak", 275), new Product("Lifejacket", 48.95)]; console.log(`Array Value: ${getValue(products, "price")}`); console.log(`Single Total: ${getValue(products[0], "price")}`);

Tipos são inferidos com o infer e eles introduzem um generic type que tipara por inferencia pelo compilador quando o conditional type é resolvido como mostrado abaixo:

image_4.png

No código o tipo U é inferido se T é um array. O tipo de U é inferido pelo compiler do generic type parameter T quando o tipo é resolvido. O efeito é este tipo do targetKeys<Product> e o targetKeys<Product[]> ambos produzindo a união "name" | "price"

O conditional type pode ser empregado para restringir a propriedade da função getValue<T, P>, provendo uma tipagem consistência para ambos objetos e arrays

17 December 2025