【问题标题】:TypeScript: Polymorphic this and inferring generic function parameterTypeScript:多态 this 并推断泛型函数参数
【发布时间】:2020-03-15 03:02:39
【问题描述】:

我想从传递给函数的this 关键字推断当前类的类型。出于某种原因,当我将 this 作为参数传递给函数时,TypeScript 推断类型参数 T 是 this 而不是当前类类型。

下面是我正在尝试做的一个例子。我希望BC 类都有一个field 类型为number,但是当将this 作为参数传递时,C 类中的fieldGenericArguments<this>。当手动指定类型时,一切正常(B 类示例),但从 this 推断类型并没有给出我想要的结果。

type GenericArgument<T> = T extends A<infer R> ? R : never;

function test<T>(obj: T): GenericArgument<T>  {
    // do operations
    // return ...;
}

class A<T> {
    something: T;
}

class B extends A<number> {
    field = test<B>(this); // <-- field has a type: number
}

class C extends A<number> {
    field = test(this); // <-- field has a type: GenericArgument<this> 
}

我是否需要一些额外的关键字来强制 TypeScript 使用当前类类型而不是多形 this?还是有其他方法可以实现这一点?

【问题讨论】:

    标签: typescript function generics this type-inference


    【解决方案1】:

    this 与类的类型不同。它有一个特殊的类型,多态this 类型。多态this 类型表示当前类的类型,无论当前类的类型是什么,从外部都会看到。因此,例如这是有效的:

    class A {
        getThis() { return this; }
        getA(): A { return this; }
    }
    
    class B extends A {
        method() { }
    }
    var b = new B();
    b.getThis().method(); // ok since polymorphic this is seen as B from the outside 
    b.getA().method(); // err since we are accessing on A
    

    Playground Link

    在类内部,这有一个不幸的副作用,即this 类型必须表现为一个未解析的类型参数(extends 当前类的参数)。这是因为this 的最终类型确实还没有被完全知道。

    由于多态 this 类型的行为类似于未解析的类型参数,因此打字稿在条件类型中的作用非常有限。 Typescript 通常不会解析仍包含未解析类型参数的条件类型。

    在类外部,field 的类型将被正确解析,因为多态 this 被解析为我们访问 field 的任何类型。如果something 的类型被派生类缩小(这是可能的),我们甚至可能会有一些惊喜:

    class C extends A<number> {
        field = test(this); // <-- field has a type: GenericArgument<this> 
    }
    new C().field // is number
    class D extends C {
        something!: 1
    }
    new D().field // is of type number literal type 1
    
    

    Playground Link

    明确字段编号的解决方法可能是最简单的解决方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-05
      • 2020-01-23
      • 2020-03-11
      • 1970-01-01
      • 2016-11-01
      • 1970-01-01
      • 2020-09-09
      • 2017-06-02
      相关资源
      最近更新 更多