简体   繁体   English

如何推断通用属性类型?

[英]How to Infer Generic Property Types?

I can't figure out how to infer the type of a generic property based on the generic type of the object it's on.我不知道如何根据它所在对象的泛型类型来推断泛型属性的类型。 In the following example, how can I say that Something.aProp needs to match the type of Something's U.obj.prop ?在下面的例子中,我怎么能说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;
}

Ie Something<Parent>.aProp should be of type Prop , and Something<FancyParent>.aProp is of type FancyProp ?Something<Parent>.aProp应该是Prop类型,而Something<FancyParent>.aPropFancyProp类型?

For your main question, the way to look up the type of a property value given an object type T and a key type K is to use lookup types, aka, indexed access types , via the bracket syntax T[K] .对于您的主要问题,在给定对象类型T和键类型K情况下查找属性值类型的方法是通过括号语法T[K]使用查找类型,也就是索引访问类型 So if you want to look up the type of the "prop" -keyed property of the "obj" -keyed property of an object of type U , you would write that type as U["obj"]["prop"] .因此,如果您想查找U类型对象的"obj"键控属性的"prop"键控属性的类型,您可以将该类型写为U["obj"]["prop"]

Note that dot syntax doesn't work for types, even if the key types are string literals.请注意,点语法不适用于类型,即使键类型是字符串文字。 It would be nice if U.obj.prop were a synonym for U["obj"]["prop"] in the type system, but unfortunately that syntax would collide with namespaces , since there could be a namespace named U , with a subnamespace named obj , with an exported type named prop , and then U.obj.prop would refer to that type.如果U.obj.prop是类型系统中U["obj"]["prop"]的同义词U.obj.prop了,但不幸的是,该语法会与 namespaces 发生冲突,因为可能有一个名为U的命名空间,带有名为obj子命名空间,具有名为prop的导出类型,然后U.obj.prop将引用该类型。


For your comments about any , it's not really wrong to use X extends Y<any> when Y<T> 's type parameter T has a generic constraint , but it might be a bit less type safe than you can get.对于您对any的评论,当Y<T>的类型参数T具有泛型约束时,使用X extends Y<any>并没有,但它的类型安全性可能比您所能获得的要低一些。 If the type Y<T> is related to T in a covariant way, then you can use the generic constraint instead of any .如果类型Y<T>协变方式与T相关,那么您可以使用泛型约束而不是any

That would mean, for example, Parent<T extends Obj<any>> could be replaced with Parent<T extends Obj<Prop>> , and U extends Parent<any> could be replaced with U extends Parent<Obj<Prop>> .这意味着,例如, Parent<T extends Obj<any>>可以替换为Parent<T extends Obj<Prop>> ,而U extends Parent<any>可以替换为U extends Parent<Obj<Prop>> .


Those changes give you code like this:这些更改为您提供如下代码:

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;
    }
}

I also added a constructor to Something because class properties should be initialized and I wanted to show that aProp could be assigned with a value from u.obj.pop when u is a U .我还向Something添加了一个构造函数,因为应该初始化类属性,并且我想表明当uU时,可以为aProp分配来自u.obj.pop的值。

And this should work as you expect:这应该按您的预期工作:

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

Okay, hope that helps;好的,希望有帮助; good luck!祝你好运!

Playground link to code Playground 链接到代码

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

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