Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить Extract<T, U>?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Extract<T, U>** вибирає з `T` тільки ті підтипи, які сумісні (assignable) з `U`, реалізуючись як `T extends U ? T : never`. **Ключове:** Extract працює дистрибутивно по `T` - кожен член об'єднання перевіряється окремо, і разом з `Exclude<T, U>` вони розкладають `T` на дві частини без перетину.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що робить `Extract<T, U>`? Вибирає з `T` тільки ті підтипи, які **сумісні** (assignable) з `U`. Реалізація в lib.d.ts еквівалентна: ```javascript type Extract<T, U> = T extends U ? T : never; ``` Приклади: ```javascript type A = Extract<string | number | boolean, number | boolean>; // number | boolean type B = Extract<"a" | "b" | 1, string>; // "a" | "b" type C = Extract<{a:1} | {b:2}, {a:1} | {c:3}>; // {a:1} type D = Extract<"get" | "set" | "reset", `get${string}`>; // "get" type E = Extract<null | undefined | 0, null | undefined>; // null | undefined ``` ## Чим `Extract` протилежний до `Exclude`? `Exclude<T, U>` робить зворотне: **прибирає** з `T` все, що сумісне з `U`. ```javascript type Exclude<T, U> = T extends U ? never : T; ``` Співвідношення: - `Extract<T, U> | Exclude<T, U> === T` (декомпозиція множини) - `Extract<T, U> & Exclude<T, U> === never` (вони не перетинаються) - Тотожність: `Extract<T, U> === Exclude<T, Exclude<T, U>>` Міні-приклад: ```javascript type T = string | number | boolean; type OnlyStrings = Extract<T, string>; // string type NotStrings = Exclude<T, string>; // number | boolean ``` ## Як `Extract` працює з union-типами? Дистрибутивно по `T`: кожен член об'єднання з `T` перевіряється на сумісність з `U`; ті, що проходять, - об'єднуються, ті, що ні - відкидаються. ```javascript type R1 = Extract<"a" | 1 | true, string | number>; // "a" | 1 type R2 = Extract<{x:1} | {y:2}, {x:1}>; // {x:1} type R3 = Extract<never, string>; // never ``` Тонкощі: - З `any`: - `Extract<T, any>` -> завжди `T`. - `Extract<any, U>` -> `any` (через особливі правила умовних типів з `any`). - З `unknown`: - `Extract<T, unknown>` -> `T` (все сумісне з `unknown`). - `Extract<unknown, U>` -> `never` (окрім випадків, коли `unknown` явно сумісний з `U`, що зазвичай не так). - З `never`: завжди `never`. Практичні кейси: ```javascript // Дістаємо ключі-рядки зі змішаного union type Keys = Extract<keyof any, string>; // string | number | symbol ∩ string = string // Фільтруємо union за форматом рядка: type HttpGet = Extract<"GET" | "POST" | "PUT", "GET" | "HEAD">; // "GET" // Вибираємо лише функції: type Fn = Extract<string | (() => void) | { run(): void }, Function>; // () => void ```Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.