programowanieTypeScript/Fullstack deweloper

Jak działają Conditional Types z infer w TypeScript, w jakich sytuacjach są potrzebne i jakie błędy spotyka się w praktyce?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

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:

  • Do pisania uniwersalnych typów pomocniczych (na przykład wydobywanie rodzaju zwracanego przez funkcję, typu wartości Promise itd.).

Przykład:

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

Pytanie z haczykiem.

Czy można użyć więcej niż jednego infer w jednym typie warunkowym? Jak TypeScript interpretuje ten przypadek?

Błędna odpowiedź:

  • „Nie można używać więcej niż jednego infer, TypeScript na to nie pozwala.”

Prawidłowa odpowiedź:

  • Można używać wielu zmiennych infer w jednym wzorze. Na przykład, analizując krotkę:
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;
  • TypeScript poprawnie wyprowadza wiele typów przez różne zmienne infer.

Przykłady rzeczywistych błędów z powodu braku znajomości niuansów tematu.


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.