简体   繁体   English

TypeScript:多态 this 并推断通用 function 参数

[英]TypeScript: Polymorphic this and inferring generic function parameter

I would like to infer the type of the current class from this keyword passed to a function.我想从传递给 function 的this关键字推断当前 class 的类型。 For some reason when i'm passing this as a parameter to the function, TypeScript infers that type parameter T is this instead of the current class type.由于某种原因,当我this作为参数传递给 function 时,TypeScript 推断类型参数 T 是this而不是当前的 class 类型。

Below there is an example of what i'm trying to do.下面有一个我正在尝试做的例子。 I want both B and C class to have a field with a type number , but the field in C class is GenericArguments<this> when passing this as argument. I want both B and C class to have a field with a type number , but the field in C class is GenericArguments<this> when passing this as argument. When type is specified manually everything works fine ( B class example), but inferring the type from this does not give the results i want.当手动指定类型时,一切正常( B class 示例),但从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> 
}

Do i need some additional keyword to force TypeScript to use current class type and not polymotphic this ?我需要一些额外的关键字来强制 TypeScript 使用this的 class 类型而不是多形的吗? Or is there some other way to achieve this?还是有其他方法可以实现这一目标?

this is not of the same type as the class. this与 class 的类型不同。 It has a special type, the polymorphic this type.它有一个特殊的类型,多态的this类型。 The polymorphic this type represents the type of the current class and will be seen from the outside as whatever the type of the current class is. this类型的多态表示当前 class 的类型,无论当前 class 的类型是什么类型,都可以从外部看到。 So for example this works:因此,例如,这有效:

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 游乐场链接

From inside the class, this has the unfortunate side effect that the this type has to behave as an unresolved type parameter (one that extends the current class).从 class 内部来看,这具有不幸的副作用,即this类型必须表现为未解析的类型参数( extends当前类的参数)。 This is due to the fact that the final type of this is indeed not yet fully known. this是因为它的最终类型确实还不完全清楚。

Since the polymorphic this type is behaves like an unresolved type parameter, typescript is very limited in what it will do with it in conditional types.由于this类型的多态行为类似于未解析的类型参数,因此 typescript 在条件类型中的作用非常有限。 Typescript does not generally resolve conditional types that still contain unresolved type parameters. Typescript 通常不解析仍包含未解析类型参数的条件类型。

From outside the class, the type of field will be resolved correctly, since polymorphic this is resolved to whatever type we access field on.从 class 外部, field的类型将被正确解析,因为多态this解析为我们访问field的任何类型。 We might even have some surprises if the type of something is narrowed by a derived class (which is possible):如果something的类型被派生的 class (这是可能的)缩小范围,我们甚至可能会感到惊讶:

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 游乐场链接

The workaround of being explicit with the field number is probably the simplest one.明确使用字段编号的解决方法可能是最简单的解决方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM