【问题标题】:Typescript: How to branch based on typeTypescript:如何根据类型进行分支
【发布时间】:2019-02-06 06:20:04
【问题描述】:

我有这样的事情:

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 .... 没有一个是正确的。

【问题讨论】:

    标签: typescript if-statement types branch


    【解决方案1】:

    接口在运行时不存在,它们完全是编译时构造。所以没有办法在表达式中使用类型,因为在运行代码时类型不会存在。

    我们能做的最好的就是创建一个包含接口的所有键的对象,编译器保证包含接口的所有键并且只包含接口的键

    然后我们可以在自定义类型保护中使用这个对象来帮助编译器缩小键的类型。

    一般的解决方案如下所示:

    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');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 2022-01-24
      • 2021-07-13
      • 2019-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多