[英]Dynamic generic type inference for object literals in TypeScript
在typescript中,我可以像这样声明一个泛型函数:
const fn: <T>(arg: T)=>Partial<T>
在这种情况下,TypeScript有时可以根据我传递的实际参数推断函数的类型参数。 是否有类似的方法来定义一个通用对象文字,其类型参数可以根据其内容动态推断 ? 就像是:
interface XYZ {
obj: <T>{ arr: T[], dict: Partial<T> }
}
我知道我可以使整个界面像这样通用:
interface XYZ<T> {
arr: T[],
dict: Partial<T>
}
但我想避免这种情况,因为每当我使用界面时,我都必须提前声明泛型类型。 例如
const x: XYZ
不管用。 如果我想宣布一般,我被迫写:
const x: XYZ<any>
但是这不允许TypeScript根据x
的实际内容动态推断出特定的泛型类型
啊,您需要Microsoft / TypeScript#17574中讨论的通用值。 如您所知,除通用函数外,它们不存在于语言中。 如果你愿意,你可以给这个问题做一个,,或者如果你认为它有用,可以讨论你的用例。
给定通用接口
interface XYZ<T> {
arr: T[],
dict: Partial<T>
}
我只想用这个解决方法:一个泛型函数来验证值是XYZ<T>
对于一些 T
,并允许类型推断实际推断T
时,它是必要的。 永远不要尝试声明XYZ
类型的东西。 像这样:
const asXYZ = <T>(xyz: XYZ<T>) => xyz;
const x = asXYZ({
arr: [{ a: 1, b: 2 }, { a: 3, b: 4 }],
dict: { a: 1300 }
}); // becomes XYZ<{a: number, b: number}>
以上通常在实践中对我有用。 专业人士认为它是“自然的”TypeScript。 con是它不代表“我不在乎什么类型T
是”正确。
如果你真的想要,你可以定义一个存在类型 。 TypeScript本身不支持这些,但有一种方法可以表示它:
interface SomeXYZ {
<R>(processXYZ: <T>(x: XYZ<T>) => R): R
}
const asSomeXYZ = <T>(xyz: XYZ<T>): SomeXYZ =>
<R>(processXYZ: <T>(x: XYZ<T>) => R) => processXYZ(xyz);
SomeXYZ
类型是一个不再关心T
的具体类型,但对于某些 T
,它包含对XYZ<T>
的引用。您使用asSomeXYZ
从对象创建一个:
const someXYZ: SomeXYZ = asSomeXYZ({
arr: [{ a: 1, b: 2 }, { a: 3, b: 4 }],
dict: { a: 1300 }
}); // SomeXYZ
并通过传递处理保持引用的函数来使用它。 对于任何T
,该函数必须为XYZ<T>
做好准备,因为你不知道SomeXYZ
持有什么类型的T
// use one
const xyzArrLength = someXYZ((xyz => xyz.arr.length))
xyzArrLength
是一个number
,因为函数xyz => xyz.arr.length
返回一个number
无论T
是什么。
TypeScript中的存在类型很笨拙,因为正在进行大量的控制反转。 这是这个的主要缺点,以及为什么我通常会采用我首先提出的不太完美但更容易思考的解决方法。
希望有所帮助。 祝好运!
编辑:重新阅读你的问题让我觉得你实际上是在寻求我列为“解决方法”的答案。 那么,呃......用那个? 干杯。
interface MyGenericObjectLiteral<T> {
arr: T[],
dict: Partial<T>
}
interface XYZ {
obj: MyGenericObjectLiteral<any>
}
这里的接口XYZ不是通用的,只是子对象MyGenericObjectLiteral。 它实际上就是你想要的,除了它有一点不同的语法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.