И снова Infer
По вашим просьбам сегодня разберем еще пример с infer. Я покажу, какие умозаключения я делаю, когда описываю типы при помощи этого ключевого слова.
▶️Задача: вывести тип первого аргумента функции.
const logUser = (user: 'user' | 'admin', lastLogin: Date) => {...} // 'user' | 'admin';
const repeatChat = (count: number, char: string) => {...} // number
const getStringLength = (str: string) => {...} // string
Заметим, что в функции может быть сколько угодно аргументов, но нас интересует только первый. Поэтому имеет смысл разбить аргументы на две группы: первый и все остальные, которые нас не интересуют. В JavaScript есть очень удобный оператор rest, который позволяет нам собрать все неинтересные нам аргументы в кучу.
Давайте для примера попробуем описать тип Func, которым можно описать все наши функции из примера выше, и пока будем использовать везде any. Наша задача — просто побить сигнатуру на логические группы. В параметрах выделим сначала первый x (он-то нам и интересен), затем все остальные аргументы соберем в параметр rest. Вернем any — мы договорились пока что везде использовать any. У меня получилось так:
type Func = (x: any, ...rest: any) => any;
Теперь, глядя на этот шаблон, легко поставить infer туда, куда нам интересно. Псевдокодом получится вот так:
type Func = (x: infer U, ...rest: any) => any;
Осталось написать наш тип-дженерик по общему алгоритму: проверяем, соответствует ли параметр типа нашему шаблону, если да, возвращаем интересный нам U, иначе never.
type FirstArg =
T extends (x: infer U, ...args: any) => any
? U
: never;
#typescript
🔜 Канал в MAX
По вашим просьбам сегодня разберем еще пример с infer. Я покажу, какие умозаключения я делаю, когда описываю типы при помощи этого ключевого слова.
▶️Задача: вывести тип первого аргумента функции.
const logUser = (user: 'user' | 'admin', lastLogin: Date) => {...} // 'user' | 'admin';
const repeatChat = (count: number, char: string) => {...} // number
const getStringLength = (str: string) => {...} // string
Заметим, что в функции может быть сколько угодно аргументов, но нас интересует только первый. Поэтому имеет смысл разбить аргументы на две группы: первый и все остальные, которые нас не интересуют. В JavaScript есть очень удобный оператор rest, который позволяет нам собрать все неинтересные нам аргументы в кучу.
Давайте для примера попробуем описать тип Func, которым можно описать все наши функции из примера выше, и пока будем использовать везде any. Наша задача — просто побить сигнатуру на логические группы. В параметрах выделим сначала первый x (он-то нам и интересен), затем все остальные аргументы соберем в параметр rest. Вернем any — мы договорились пока что везде использовать any. У меня получилось так:
type Func = (x: any, ...rest: any) => any;
Теперь, глядя на этот шаблон, легко поставить infer туда, куда нам интересно. Псевдокодом получится вот так:
type Func = (x: infer U, ...rest: any) => any;
Осталось написать наш тип-дженерик по общему алгоритму: проверяем, соответствует ли параметр типа нашему шаблону, если да, возвращаем интересный нам U, иначе never.
type FirstArg =
T extends (x: infer U, ...args: any) => any
? U
: never;
#typescript
🔜 Канал в MAX