TypeScript: продвинутые типы
Utility Types
Встроенные преобразования типов — generic-типы, которые принимают один или несколько типов-аргументов и возвращают новый преобразованный тип. Уменьшают дублирование.
type User = { id: number; name: string; email?: string };
Partial<User>; // все поля необязательные
Required<User>; // все поля обязательные
Readonly<User>; // все поля только для чтения
Pick<User, "id" | "name">; // выборка полей
Omit<User, "email">; // исключение полей
Record<string, number>; // объект с заданными ключами/значениямиConditional Types (условные типы)
Тип, определяемый по условию на основе другого типа.
type Check<T> = T extends Condition ? TrueType : FalseType;
type ToUnion<T> = T extends any[] ? T[number] : T;
type A = ToUnion<number[]>; // number
type B = ToUnion<string>; // stringinfer
infer извлекает (выводит) тип внутри условного типа. Используется только в контексте conditional types.
type ElementType<T> = T extends Array<infer U> ? U : never;
type X = ElementType<number[]>; // numberunknown vs any
any | unknown | |
|---|---|---|
| Присваивание в него | любой тип | любой тип |
| Операции над значением | разрешены любые | запрещены без проверки типа |
| Безопасность | отключает проверку типов | требует сузить тип перед использованием |
let a: any;
a.foo.bar; // ок — проверок нет (опасно)
let u: unknown;
u.foo; // ❌ ошибка — сначала нужно сузить тип
if (typeof u === "string") u.toUpperCase(); // окИспользуй
unknown, когда просто пробрасываешь входное значение дальше;any— когда осознанно отключаешь проверки.
never
never — тип, который никогда не возникает. Нижний тип (bottom type): подтип любого типа, но ни один тип не является подтипом never.
function throwError(message: string): never {
throw new Error(message);
}
// exhaustiveness check
function processColor(color: "red" | "blue") {
switch (color) {
case "red": break;
case "blue": break;
default:
const _exhaustive: never = color; // ошибка, если добавить новый вариант
}
}