Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як дістати тип аргументів функції через infer?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Тип аргументів функції можна дістати через умовний тип з `infer`, наприклад `type Args<T> = T extends (...args: infer A) => any ? A : never`. **Ключове:** `infer` "витягує" аргументи у вигляді кортежу, а якщо `T` не є функцією, результатом буде `never`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)ЗображенняTypeScript дозволяє **дістати тип аргументів функції** за допомогою ключового слова `infer` усередині **умовних типів**. Це один із найчастіших і найкорисніших кейсів використання `infer`. --- ## Загальна ідея Ми перевіряємо, що якийсь тип `T` - це **функція**, і кажемо TypeScript: > "Якщо `T` - це функція, аргументи якої мають тип `A`, то виведи цей `A`." --- ## Приклад 1: Дістати тип *одного аргументу* ```javascript type FirstArg<T> = T extends (arg: infer A) => any ? A : never; type Example = (x: number) => void; type Result = FirstArg<Example>; // number ``` Тут: - `T extends (arg: infer A) => any` - перевірка, чи є `T` функцією. - `infer A` - TypeScript "витягує" тип першого аргументу. - Якщо `T` не функція, результатом буде `never`. --- ## Приклад 2: Дістати **всі аргументи функції** у вигляді кортежу ```javascript type Args<T> = T extends (...args: infer A) => any ? A : never; type Fn = (x: number, y: string) => boolean; type Params = Args<Fn>; // [number, string] ``` `infer A` у цьому випадку стає **кортежем типів аргументів**. --- ## Приклад 3: Дістати **тип значення, яке повертається** ```javascript type Return<T> = T extends (...args: any[]) => infer R ? R : never; type Fn = (x: number, y: string) => boolean; type R = Return<Fn>; // boolean ``` > Це - реалізація вбудованого типу `ReturnType<T>`. --- ## Приклад 4: Отримати і аргументи, і результат ```javascript type FunctionParts<T> = T extends (...args: infer A) => infer R ? { args: A; return: R } : never; type Fn = (id: string, active: boolean) => number; type Parts = FunctionParts<Fn>; /* { args: [string, boolean]; return: number; } */ ``` --- ## Приклад 5: Перший елемент аргументів ```javascript type FirstArg<T> = T extends (...args: [infer First, ...any[]]) => any ? First : never; type Fn = (name: string, age: number) => void; type A = FirstArg<Fn>; // string ``` > Тут використовується розпакування кортежів: `[infer First, ...any[]]`. --- ## Приклад 6: Останній аргумент ```javascript type LastArg<T> = T extends (...args: [...any[], infer Last]) => any ? Last : never; type Fn = (a: number, b: string, c: boolean) => void; type L = LastArg<Fn>; // boolean ``` --- ## Приклад 7: Тип аргументів у методу класу ```javascript class User { save(id: number, active: boolean) {} } type MethodArgs = Args<User["save"]>; // [number, boolean] ``` > Працює для будь-яких методів - просто беремо тип за ключем `["methodName"]` і застосовуємо утиліту. --- ## Приклад 8: Реалізація аналога вбудованого `Parameters<T>` TypeScript уже містить готовий утилітний тип: ```javascript type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer A) => any ? A : never; type Fn = (x: number, y: string) => boolean; type Params = MyParameters<Fn>; // [number, string] ``` Це еквівалент стандартного `Parameters<Fn>`. --- ## Приклад 9: Отримати тип аргументів callback-функції ```javascript type Callback = (err: Error | null, data: string) => void; type CallbackArgs = Args<Callback>; // [Error | null, string] ``` > Часто використовується в типізації API, Node.js колбеків, React-хуків тощо. --- ## Приклад 10: Застосувати аргументи до іншої функції ```javascript type Args<T> = T extends (...args: infer A) => any ? A : never; function call<T extends (...args: any[]) => any>(fn: T, ...args: Args<T>) { return fn(...args); } function greet(name: string, age: number) { return `${name}, ${age}`; } call(greet, "Tim", 25); // ok call(greet, 25, "Tim"); // помилка типів ``` Тут `Args<T>` гарантує правильний порядок і типи аргументів. --- ## Підсумок | Що дістаємо | Приклад | Результат | |---|---|---| | Один аргумент | `T extends (a: infer A) => any` | тип першого аргументу | | Всі аргументи | `T extends (...args: infer A) => any` | кортеж аргументів | | Повернення | `T extends (...args: any[]) => infer R` | тип результату | | Перший аргумент | `T extends (...args: [infer F, ...any[]]) => any` | перший аргумент | | Останній аргумент | `T extends (...args: [...any[], infer L]) => any` | останній аргумент |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.