@vlad_mishustin
TS ❤️

Почему типы написаны так?

Увидел в исходниках одного приложения такие типы без пояснений:
type Exist<T> = T extends undefined | null ? never : T;

type PickFromObject<O extends Record<PropertyKey, unknown>, K> =
  K extends keyof O
    ? O[K]
    : K extends keyof Exist<O>
      ? Exist<O>[K]
      : undefined;

type PickFromArray<A extends readonly any[], K> = any[] extends A
  ? A extends readonly (infer T)[]
    ? T | undefined
    : undefined
  : K extends keyof A
    ? A[K]
    : undefined;


Не совсем понимаю для чего в первом типе используют K extends keyof Exist<O>, вместо простого возврата undefined.

Во втором не понимаю сразу несколько вещей: почему изначально проверка any[] extends A и как работает
? A extends readonly (infer T)[]
 : K extends keyof A
, то есть первое условие с infer может не отработать?

Объясните, пожалуйста, очень интересно)
  • Вопрос задан
  • 84 просмотра
Пригласить эксперта
Ответы на вопрос 1
Alexandroppolus
@Alexandroppolus
кодир
для чего в первом типе используют K extends keyof Exist< O >

Exist - то же самое, что утилитарный тип NonNullable, он выкидывает из типа O значения undefined и null, что в данном случае абсолютно бессмысленно, ибо на О уже есть ограничение, которому нуллы не соответствуют.

почему изначально проверка any[] extends A

потому что условию extends readonly any[] соответствуют как массивы, так и кортежи. any[] extends A - проверка, что это именно массив.

условие с infer точно отработает, оно соответствует исходному ограничению на А. Но оно здесь опять же не в тему, потому что PickFromArray< number[], 'qqq' > дает number | undefined, что разумеется бред.

K extends keyof A рассматривается для кейса, когда А оказался не массивом, а кортежем.

в целом написано довольно бестолково, возможно с помощью чатаГПТ
предложу более универсальный вариант
type PickFromObject<O extends {}, K> = O extends O ? K extends K
  ? number extends K
    ? O[K & keyof O] | undefined
    : `${number}` extends K
      ? O[K & keyof O] | undefined
      : [never[], K] extends [O, number | `${number}`]
        ? O[K & keyof O] | undefined
        : K extends keyof O ? O[K] : undefined
  : never : never;


этот PickFromObject работает как с объектами, так и с массивами/кортежами
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы