Интерфейсы не существуют во время выполнения, они являются исключительно конструкцией во время компиляции.Таким образом, нет никакого способа использовать тип в выражении, так как тип не будет присутствовать при выполнении кода.
Лучшее, что мы можем сделать, - это создать объект, который содержит все ключи интерфейса, который - это компилятор, который гарантированно содержит все ключи интерфейса и только ключи интерфейса
Затем мы можем использовать этот объект в настраиваемой защите типов, чтобы помочь компилятору сузить типключ.
Общее решение будет выглядеть примерно так:
interface A {
a1: string;
a2: number;
a3?: boolean;
}
interface B {
b1: number;
b2: boolean;
b3: string;
}
// Factory function for key type-guards
function interfaceKeys<T>(keys: Record<keyof T, 0>) {
return function (o: PropertyKey): o is keyof T {
return o in keys;
}
}
// The objects here are compiler enforced to have all the keys and nothing but the keys of each interface
const isAkey = interfaceKeys<A>({ a1: 0, a2: 0, a3: 0 })
const isBkey = interfaceKeys<B>({ b1: 0, b2: 0, b3: 0 })
function foo<K1 extends keyof A, K2 extends keyof B>(input: K1 | K2) {
if (isAkey(input)) { // custom type guard usage
console.log('got A type');
input // is K1
} else {
console.log('got B type');
input // is K2
}
}
foo('a1');
foo('b2');