如何推断泛型 属性 类型?
How to Infer Generic Property Types?
我不知道如何根据其所在对象的通用类型推断通用 属性 的类型。在下面的例子中,我怎么能说 Something.aProp
需要匹配 Something 的 U.obj.prop
的类型?
interface Prop {
a: number;
}
interface FancyProp extends Prop {
b: number;
}
interface Obj<T extends Prop> {
prop: T;
}
interface FancyObj extends Obj<FancyProp> {}
interface Parent<T extends Obj<any>> { // <-- the <any> here seems wrong too
obj: T;
}
interface FancyParent extends Parent<FancyObj> {
fancy: number;
}
class Something<U extends Parent<any>> {
aProp: typeof U.obj.prop;
}
即Something<Parent>.aProp
应该是 Prop
类型,Something<FancyParent>.aProp
应该是 FancyProp
?
类型
对于您的主要问题,在给定对象类型 T
和键类型 K
的情况下查找 属性 值类型的方法是使用 lookup types, a.k.a., indexed access types, 通过括号语法 T[K]
。因此,如果你想查找 U
类型对象的 "prop"
键控 属性 的 "obj"
键控 属性 的类型,你会将该类型写为 U["obj"]["prop"]
.
请注意,点语法不适用于类型,即使键类型是字符串文字也是如此。如果 U.obj.prop
在类型系统中是 U["obj"]["prop"]
的同义词就好了,但是 unfortunately that syntax would collide with namespaces,因为可以有一个名为 U
的命名空间,以及一个名为 obj
,带有名为 prop
的导出类型,然后 U.obj.prop
将引用该类型。
关于您对 any
的评论,在 Y<T>
的类型参数 [=12= 时使用 X extends Y<any>
并不是真的 错误 ] 有一个 generic constraint, but it might be a bit less type safe than you can get. If the type Y<T>
is related to T
in a covariant 的方式,那么你可以使用通用约束而不是 any
。
这意味着,例如,Parent<T extends Obj<any>>
可以替换为 Parent<T extends Obj<Prop>>
,而 U extends Parent<any>
可以替换为 U extends Parent<Obj<Prop>>
。
这些更改为您提供了如下代码:
interface Parent<T extends Obj<Prop>> {
obj: T;
}
class Something<U extends Parent<Obj<Prop>>> {
aProp: U['obj']['prop'];
constructor(u: U) {
this.aProp = u.obj.prop;
}
}
我还向 Something
添加了一个构造函数,因为 class properties should be initialized 并且我想证明 aProp
可以从 u.obj.pop
中赋值 u
是 U
.
这应该会像您预期的那样工作:
interface PlainObj extends Obj<Prop> { }
interface PlainParent extends Parent<PlainObj> { }
new Something<PlainParent>({ obj: { prop: { a: 1 } } }).aProp.a; // number
interface FancyObj extends Obj<FancyProp> { }
interface FancyParent extends Parent<FancyObj> {
fancy: number;
}
new Something<FancyParent>({ obj: { prop: { a: 1, b: 2 } }, fancy: 3 }).aProp.b; // number
好的,希望对您有所帮助;祝你好运!
我不知道如何根据其所在对象的通用类型推断通用 属性 的类型。在下面的例子中,我怎么能说 Something.aProp
需要匹配 Something 的 U.obj.prop
的类型?
interface Prop {
a: number;
}
interface FancyProp extends Prop {
b: number;
}
interface Obj<T extends Prop> {
prop: T;
}
interface FancyObj extends Obj<FancyProp> {}
interface Parent<T extends Obj<any>> { // <-- the <any> here seems wrong too
obj: T;
}
interface FancyParent extends Parent<FancyObj> {
fancy: number;
}
class Something<U extends Parent<any>> {
aProp: typeof U.obj.prop;
}
即Something<Parent>.aProp
应该是 Prop
类型,Something<FancyParent>.aProp
应该是 FancyProp
?
对于您的主要问题,在给定对象类型 T
和键类型 K
的情况下查找 属性 值类型的方法是使用 lookup types, a.k.a., indexed access types, 通过括号语法 T[K]
。因此,如果你想查找 U
类型对象的 "prop"
键控 属性 的 "obj"
键控 属性 的类型,你会将该类型写为 U["obj"]["prop"]
.
请注意,点语法不适用于类型,即使键类型是字符串文字也是如此。如果 U.obj.prop
在类型系统中是 U["obj"]["prop"]
的同义词就好了,但是 unfortunately that syntax would collide with namespaces,因为可以有一个名为 U
的命名空间,以及一个名为 obj
,带有名为 prop
的导出类型,然后 U.obj.prop
将引用该类型。
关于您对 any
的评论,在 Y<T>
的类型参数 [=12= 时使用 X extends Y<any>
并不是真的 错误 ] 有一个 generic constraint, but it might be a bit less type safe than you can get. If the type Y<T>
is related to T
in a covariant 的方式,那么你可以使用通用约束而不是 any
。
这意味着,例如,Parent<T extends Obj<any>>
可以替换为 Parent<T extends Obj<Prop>>
,而 U extends Parent<any>
可以替换为 U extends Parent<Obj<Prop>>
。
这些更改为您提供了如下代码:
interface Parent<T extends Obj<Prop>> {
obj: T;
}
class Something<U extends Parent<Obj<Prop>>> {
aProp: U['obj']['prop'];
constructor(u: U) {
this.aProp = u.obj.prop;
}
}
我还向 Something
添加了一个构造函数,因为 class properties should be initialized 并且我想证明 aProp
可以从 u.obj.pop
中赋值 u
是 U
.
这应该会像您预期的那样工作:
interface PlainObj extends Obj<Prop> { }
interface PlainParent extends Parent<PlainObj> { }
new Something<PlainParent>({ obj: { prop: { a: 1 } } }).aProp.a; // number
interface FancyObj extends Obj<FancyProp> { }
interface FancyParent extends Parent<FancyObj> {
fancy: number;
}
new Something<FancyParent>({ obj: { prop: { a: 1, b: 2 } }, fancy: 3 }).aProp.b; // number
好的,希望对您有所帮助;祝你好运!