【问题标题】:Infer class generics when using `instanceof`使用“instanceof”时推断类泛型
【发布时间】:2022-11-30 18:23:12
【问题描述】:

假设我们有以下代码:

class Foo<T = number> {
  foo: T;

  constructor(foo: T) {
    this.foo = foo;
  }
}

const F: typeof Foo<number> = Foo;

let f: unknown;

if (f instanceof F) {
  f.foo; // 'any', why is this not a 'number'?
}

Playground

为什么 f 的类型是 Foo&lt;any&gt; 而不是 Foo&lt;number&gt;?我可以只使用instanceof 来完成这项工作还是必须使用type predicates function

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    你可以使用类型保护,例如

    function isF(isF: unknown): isF is Foo<number>{
      return isF instanceof F;
    }
    
    if (isF(f)) {
      f.foo; // Foo<number>
    }
    

    【讨论】:

    • 是的,我就是这么想的。但是仍然想知道是否有一种方法可以只使用 instanceof 来做到这一点,因为我们不能这样做似乎很奇怪。
    【解决方案2】:

    通过检查f instanceof F来假设f的类型是Foo&lt;number&gt;是不安全的。 instanceof 运算符不关心泛型,因为它们在运行时被擦除。

    我们可以毫无问题地用new Foo("a string")实例化ff instance F 将返回 true,即使 f 的类型为 Foo&lt;string&gt;

    const F: typeof Foo<number> = Foo;
    
    let f: unknown = new Foo("a string")
    
    console.log(f instanceof F)
    // true
    
    if (f instanceof F) {
      console.log(f.foo);
      // "a string"
    }
    

    Playground

    【讨论】:

    • 当然可以,但是您不能使用字符串实例化 F。这就是为什么我觉得它很奇怪。
    • 你怎么觉得这很奇怪?我证明了 instanceof 运算符可以不是以将 Foo&lt;number&gt; 与任何其他 Foo 区分开来的方式使用。我们只能确保f 是某种类型Foo。由于没有更多可用信息,编译器会将 T 替换为 any
    猜你喜欢
    • 2010-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多