Как сделать, чтобы ключи интерфейса соответствовали списку ключей?
Есть перечисленные ключи:
type Keys = 'a' | 'b' | 'c';
Они могут быть взяты например из другого интерфейса через keyof, или могут быть просто перечислены как тут.
И есть другие интерфейсы, которые должны иметь именно эти ключи, и никакие больше:
interface X {
a: number;
b: string;
c: MyAnytype;
z: number; // должна быть ошибка - лишний ключ "z"
}
interface Y { // должна быть ошибка - не найден ключ "b"
a: 'some-type';
c: Function;
}
В значениях могут быть любые типы, которые я перечислю руками, не автоматические как в {[key in Keys]: number}. Типы значений не должны никак расширяться или подменяться более общими или другими.
Как добиться такой проверки ключей у типов?
Ответы (2 шт):
Сделал такой костыль-проверяльщик:
type Check = {
[key in Keys]: X[key];
} | {
[key in keyof X]: { [innerKey in Keys]: any }[key];
}
Он проверяет ключи в "обе стороны". При несоответствии списка интерфейсу, или интерфейса списку, подсвечивается ошибкой какая-то из строк данного проверяльщика. Годится, чтобы не прошло компиляцию.
Но нужно нормальное решение.
Использовать utility-тип Record - создает тип, который является записью с ключами, определенными в первом параметре, и значениями типа, определенного во втором параметре. Порядок значений произвольный.
type Keys = 'a' | 'b' | 'c';
type AnyType = { value: number }
type TObject = Record<Keys, number | string | AnyType>
Для проверки:
let x: TObject = {
a: 4,
b: 'string',
c: {value: 5},
}