Conditional Types z wykorzystaniem słowa kluczowego infer pozwalają na wydobywanie typów z złożonych typów danych. Klasyczny przykład — wydobywanie typu elementu z tablicy:
type ElementType<T> = T extends (infer U)[] ? U : T;
Tutaj infer U pozwala obliczyć typ elementu tablicy T. Jeśli T jest tablicą, zwrócony zostanie typ jego elementów, w przeciwnym razie — sam T.
Gdzie są używane:
Przykład:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
Czy można użyć więcej niż jednego infer w jednym typie warunkowym? Jak TypeScript interpretuje ten przypadek?
Błędna odpowiedź:
Prawidłowa odpowiedź:
type FirstArgument<T> = T extends (infer F, ...any[]) => any ? F : never; // Ale poprawniej z funkcjami: type Args<T> = T extends (...args: infer A) => any ? A : never;
Historia
Programista napisał sposób na uzyskanie typu obiektu zwracanego przez funkcję, ale nie uwzględnił, że funkcja może zwracać Promise. W rezultacie typ zwracanego wyniku był zawsze Promise<any>, ponieważ nie użyto zagnieżdżonego conditional z extract/infer. Konieczne było refaktoryzowanie kodu w całej bazie.
Historia
W projekcie wprowadzono uniwersalny typ do rozpakowywania zagnieżdżonych tablic, ale zapomniano o zapisaniu końcowej gałęzi else w warunku. TypeScript nie zgłaszał błędów, ale w niektórych przypadkach wynik był never, co powodowało awarie niektórych typizacji utility w zewnętrznych bibliotekach.
Historia
Kolega próbował wydobyć typy właściwości z dużego interfejsu za pomocą combine-conditional/infer-type, nie uwzględnił, że niektóre właściwości były uniami. W rezultacie na wyjściu otrzymano niespodziewane kombinacje typów unii, kompilator je pomijał, a logika działała niepoprawnie.