啊,您需要Microsoft/TypeScript#17574 中讨论的通用值。正如您所注意到的,它们在语言中不存在,除非是泛型函数。如果您愿意,可以对这个问题给予 ?,或者如果您认为有帮助,可以讨论您的用例。
给定通用接口
interface XYZ<T> {
arr: T[],
dict: Partial<T>
}
我只想使用这个解决方法:创建一个通用函数来验证 some T 的值是 XYZ<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。缺点是它不能正确代表“我不在乎T 是什么类型”。
如果你真的想要,你可以定义一个existential type。 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>,因为你不知道T 和SomeXYZ 持有什么类型。
// use one
const xyzArrLength = someXYZ((xyz => xyz.arr.length))
xyzArrLength 是一个number,因为无论T 是什么,函数xyz => xyz.arr.length 都会返回一个number。
TypeScript 中的现有类型很尴尬,因为发生了很多控制反转。这是它的主要缺点,也是为什么我通常会采用我首先提出的不太完美但更容易思考的解决方法。
希望对您有所帮助。祝你好运!
编辑:重新阅读您的问题让我觉得您实际上是在询问我列为“解决方法”的答案。所以,呃……用那个?干杯。