typescript - 如何推断通用属性类型?
问题描述
我不知道如何根据它所在对象的泛型类型推断泛型属性的类型。在下面的例子中,我怎么能说Something.aProp
需要匹配 Something's 的类型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
使用查找类型,即索引访问类型T[K]
。因此,如果您想查找 type 对象的"prop"
-keyed 属性的"obj"
-keyed 属性的类型U
,您可以将该类型写为U["obj"]["prop"]
。
请注意,点语法不适用于类型,即使键类型是字符串文字。如果U.obj.prop
是类型系统中的同义词就好了U["obj"]["prop"]
,但不幸的是,该语法会与 namespaces 冲突,因为可能有一个名为 的命名空间U
,一个名为 的子命名空间,一个名为obj
的导出类型prop
,然后U.obj.prop
会引用该类型。
对于您对 的评论,使用when的类型参数具有泛型约束any
并没有错,但它的类型安全性可能比您所能获得的要少一些。如果类型以协变方式相关,那么您可以使用泛型约束而不是. X extends Y<any>
Y<T>
T
Y<T>
T
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
因为应该初始化类属性,并且我想表明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
好的,希望有帮助;祝你好运!
推荐阅读
- github - GitHub 开源项目中的 `xxx@xxx` 是什么意思?
- spring - 在 WAS 9 上运行的 Spring Boot 应用程序最终无法连接到 DB2 数据库
- node.js - Node.js Web 服务使用 Puppeteer 创建 PDF 创建空 PDF 文件
- c# - 使用实体框架读取 SQL Server 表时对象名称无效
- swift - MacOS 中的 WkWebView 在本地或远程内容上保持空白
- javascript - 如何在 ajax 中为 data.d 创建一个列表?
- sql-server - 如何从 Transact-SQL (T-SQL) 中的 SQL 视图中删除 SQL 数据透视表
- python - 将 DataFrame 作为一行附加到更大的 DataFrame
- c3p0 - C3P0 的 checkoutTimeout 设置干扰了登录失败异常
- c# - 在多媒体选择器中使用文件夹