Как предотвратить ошибку в TS при используя keyof?

Когда вы используете оператор keyof в TypeScript, он возвращает объединение всех ключей объекта (или типа), на основе которого вы вызываете этот оператор. Это очень полезный оператор, который позволяет вам работать с типами без необходимости жестко кодировать ключи объекта в своем коде.

Однако, при использовании keyof есть потенциальная возможность возникновения ошибок. К примеру, пусть у вас есть следующий интерфейс:

interface Person {
  name: string;
  age: number;
  location: string;
}

Вы хотите написать функцию, которая будет принимать объект типа Person и ключ, а затем возвращать значение этого ключа из объекта Person:

function getProperty(obj: Person, key: keyof Person) {
  return obj[key];
}

Однако, в случае, если вы передадите в функцию некорректный ключ, TypeScript не сможет проверить его во время компиляции, так как keyof Person возвращает объединение всех ключей типа Person.

Чтобы предотвратить ошибки при использовании keyof, вы можете воспользоваться условными типами и ключевым словом extends, чтобы ограничить допустимые значения ключей. Вот как это может выглядеть:

type SafeKeyOf<T> = {
  [K in keyof T]: T[K] extends undefined ? never : K;
}[keyof T];

function getProperty(obj: Person, key: SafeKeyOf<Person>) {
  return obj[key];
}

В этом примере мы определили тип SafeKeyOf, который исключает из объединения ключи, чьи значения являются undefined. Затем используется этот тип для ограничения значения параметра key функции getProperty.

Теперь, если вы попытаетесь передать некорректный ключ, TypeScript выдаст ошибку компиляции:

const person: Person = {
  name: "John",
  age: 30,
  location: "New York"
};

getProperty(person, "invalidKey"); // Ошибка компиляции

Таким образом, использование условных типов и ограничений с помощью extends позволяет предотвращать ошибки при использовании keyof в TypeScript. Это помогает делать ваш код более безопасным и надежным.