TypeScript:多态 this 并推断通用函数参数
TypeScript: Polymorphic this and inferring generic function parameter
我想从传递给函数的 this
关键字推断当前 class 的类型。出于某种原因,当我将 this
作为参数传递给函数时,TypeScript 推断类型参数 T 是 this
而不是当前的 class 类型。
下面是我正在尝试做的一个例子。我希望 B
和 C
class 都有一个类型为 number
的 field
,但是 C class 中的 field
当传递 this
作为参数时是 GenericArguments<this>
。当手动指定类型时,一切正常(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>
}
我是否需要一些额外的关键字来强制 TypeScript 使用当前 class 类型而不是多态 this
?或者有其他方法可以实现吗?
this
与 class 不是同一类型。它有一个特殊的类型,多态的 this
类型。多态 this
类型表示当前 class 的类型,从外部看,无论当前 class 是什么类型。因此,例如这有效:
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
从 class 内部,这有一个不幸的副作用,即 this
类型必须表现为一个未解析的类型参数(extends
当前 class).这是因为 this
的最终类型确实还没有完全知道。
由于多态 this
类型的行为类似于未解析的类型参数,因此打字稿在条件类型中对其执行的操作非常有限。 Typescript 通常不会解析仍然包含未解析类型参数的条件类型。
从 class 外部,field
的类型将被正确解析,因为多态 this
被解析为我们在 field
上访问的任何类型。如果 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
明确字段编号的解决方法可能是最简单的解决方法。
我想从传递给函数的 this
关键字推断当前 class 的类型。出于某种原因,当我将 this
作为参数传递给函数时,TypeScript 推断类型参数 T 是 this
而不是当前的 class 类型。
下面是我正在尝试做的一个例子。我希望 B
和 C
class 都有一个类型为 number
的 field
,但是 C class 中的 field
当传递 this
作为参数时是 GenericArguments<this>
。当手动指定类型时,一切正常(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>
}
我是否需要一些额外的关键字来强制 TypeScript 使用当前 class 类型而不是多态 this
?或者有其他方法可以实现吗?
this
与 class 不是同一类型。它有一个特殊的类型,多态的 this
类型。多态 this
类型表示当前 class 的类型,从外部看,无论当前 class 是什么类型。因此,例如这有效:
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
从 class 内部,这有一个不幸的副作用,即 this
类型必须表现为一个未解析的类型参数(extends
当前 class).这是因为 this
的最终类型确实还没有完全知道。
由于多态 this
类型的行为类似于未解析的类型参数,因此打字稿在条件类型中对其执行的操作非常有限。 Typescript 通常不会解析仍然包含未解析类型参数的条件类型。
从 class 外部,field
的类型将被正确解析,因为多态 this
被解析为我们在 field
上访问的任何类型。如果 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
明确字段编号的解决方法可能是最简单的解决方法。