Typescript: как переходить на основе типа - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть что-то вроде этого:

interface A {
  a1: string;
  a2: number;
  a3: boolean;
}

interface B {
  b1: number;
  b2: boolean;
  b3: string;
}

function foo<K1 extends keyof A, K2 extends keyof B>(input: K1 | K2) {
  if (input keyof A ) { // <--- THIS IS WRONG!
    console.log('got A type');
  } else {
    console.log('got B type');
  }
}

foo('a1');
foo('b2');

Как мне обновить оператор if, чтобы он правильно разветвлялся в зависимости от типа?

Я пробовал keyof, typeof, instanceof .... ни один из которых не является правильным.

1 Ответ

0 голосов
/ 06 февраля 2019

Интерфейсы не существуют во время выполнения, они являются исключительно конструкцией во время компиляции.Таким образом, нет никакого способа использовать тип в выражении, так как тип не будет присутствовать при выполнении кода.

Лучшее, что мы можем сделать, - это создать объект, который содержит все ключи интерфейса, который - это компилятор, который гарантированно содержит все ключи интерфейса и только ключи интерфейса

Затем мы можем использовать этот объект в настраиваемой защите типов, чтобы помочь компилятору сузить типключ.

Общее решение будет выглядеть примерно так:

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');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...