[英]TypeScript: How to infer the type of one generic based on another generic?
我有这个代码:
class A<T> {
a(t: T) {
console.log(t);
}
}
class B<T, O extends {b: T}> {
constructor(public a: A<O>) {
}
b(t: T) {
console.log(t)
}
}
const a = new A<{b: number}>(); // type: A<{ b: number; }>
const b = new B(a); // type: B<unknown, { b: number; }>
为什么 TypeScript 将 class B
的方法b
的参数标记为未知?
你认为它应该推导出T = number
吗? 如果条件是O equals { b: T }
(你不能写),那就是真的。 但是由于number extends {}
我们也可以有T = {}
。
在此代码中, g
将具有类型true
:
type G<T> = { b: number } extends { b: T } ? true : false;
let g: G<{}>;
我们有类型T
和O
,其中O extends {b: T}
。 T
和O['b']
之间的关系是O['b'] extends T
。 这意味着T
可以完全是O['b']
但它也可以是比O['b']
更广泛的任何类型。
typescript 无法推断这种推理方向,因为T
有无数种类型,因此number extends T
。 正如@md2perpe 所建议的那样,您可以拥有像any
或{}
这样的非常广泛的类型。 你可以有一个包含number
的联合,比如string | number
string | number
等
为了能够推断出第二个参数,我们需要以另一种方式extends
到 go。 我们需要知道T
必须比O['b']
窄。 我们可以这样写:
class B<T extends O['b'], O extends {b: any}> {
这里我们说O
是一些具有b
属性的 object。 我们说T
是某种类型,它要么是O
的b
值,要么是它的子集。 现在 typescript 将推断T
为O['b']
。
const a = new A<{b: number}>(); // type: A< b: number; }>
const b = new B(a); // type: B<number, { b: number; }>
b.b(5) // takes type: number
请注意,您仍然可以手动将T
设置为更窄的类型:
const specificB = new B<5, {b: number}>(a); // type: B<5, { b: number; }>
specificB.b(10); // error: Argument of type '10' is not assignable to parameter of type '5'.
我想我明白了这里的问题所在。 class B
有两个泛型类型参数T
和O
。 B
的构造函数只接受A<O>
类型的参数,但不接受T
类型的参数。 所以当你创建一个新的B
时,没有办法告诉T
应该绑定到什么。 尝试new B<Type1, Type2>(a)
来帮助编译器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.