Оператор keyof
Що робить keyof
keyof бере тип об'єкта (інтерфейсу, класу, літералу тощо)
і повертає об'єднання (union) усіх його ключів у вигляді рядкових (або числових) літералів.
Синтаксис:
keyof Tде T - це тип, у якого потрібно дістати ключі.
Приклад 1. Базовий приклад
type User = {
id: number;
name: string;
isAdmin: boolean;
};
type Keys = keyof User;
// "id" | "name" | "isAdmin"keyof User повернув об'єднання літеральних типів ключів
"id" | "name" | "isAdmin".
Як це працює
keyof не повертає значення, а створює тип,
який являє собою множину імен властивостей об'єкта.
Можна думати про нього як про оператор
Object.keys()
- але той, що працює на рівні типів, а не в рантаймі.
Приклад 2. З типом із числовими ключами
type Matrix = {
0: string;
1: string;
2: string;
};
type K = keyof Matrix;
// "0" | "1" | "2"Усі ключі стають рядковими літералами, навіть якщо в об'єкті були числа.
Приклад 3. Застосування з Record
type Permissions = Record<"read" | "write" | "delete", boolean>;
type K = keyof Permissions;
// "read" | "write" | "delete"Приклад 4. Застосування з typeof
keyof часто використовують разом із typeof
- щоб дістати ключі з реального об'єкта:
const user = {
id: 1,
name: "Tom",
isAdmin: true,
};
type UserKeys = keyof typeof user;
// "id" | "name" | "isAdmin"
typeof userперетворює об'єкт на його тип,keyof typeof userдістає імена ключів.
Приклад 5. У зв'язці з Index Access Types
Зазвичай keyof використовують разом з оператором індексації T[K].
type User = {
id: number;
name: string;
};
type ValueOfUser = User[keyof User];
// number | stringТак можна отримати тип усіх значень об'єкта,
аналогічно Object.values() у JS.
Приклад 6. Обмеження generic-параметрів
keyof часто використовують для обмеження generic'ів
- щоб дозволити передавати лише допустимі ключі.
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { id: 1, name: "Alex" };
getProp(user, "id"); // OK
getProp(user, "email"); // Помилка: "email" не є ключем userK extends keyof T каже:
"K має бути одним із ключів типу T".
Приклад 7. Застосування до класів
class Point {
x = 0;
y = 0;
move(dx: number, dy: number) {}
}
type Keys = keyof Point;
// "x" | "y" | "move"Приклад 8. З optional і readonly властивостями
keyof не змінює модифікатори властивостей (readonly, ?)
- він просто повертає імена.
type Config = {
readonly url: string;
timeout?: number;
};
type Keys = keyof Config;
// "url" | "timeout"Приклад 9. Застосування до union'ів
Якщо тип - об'єднання об'єктів,
keyof повертає перетин їхніх ключів (лише спільні):
type A = { a: number; shared: string };
type B = { b: boolean; shared: string };
type Keys = keyof (A | B);
// "shared"Приклад 10. Застосування до масивів
Масиви в TS - це об'єкти, тому в них теж є ключі:
type K = keyof string[];
// number | "length" | "toString" | ...Тобто
keyofповерне і числові індекси, і стандартні методи масиву.
Застосування на практиці
Перевірка коректності ключів
function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
const result = {} as Pick<T, K>;
for (const key of keys) {
result[key] = obj[key];
}
return result;
}
const user = { id: 1, name: "John", isAdmin: true };
const partial = pick(user, ["id", "name"]); // працюєПідсумок
| Поняття | Опис |
|---|---|
keyof T | Повертає об'єднання імен ключів типу T |
| Тип результату | Рядкові/числові літеральні типи ключів |
| Типове застосування | K extends keyof T, T[keyof T], keyof typeof obj |
| Аналог у JS | Схожий на Object.keys(obj) - але працює на рівні типів |
| Використовується в | Pick, Record, Partial, Omit, generic-функціях та ін. |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.