TypeScript中对象文字的动态通用类型推断

prm*_*mph 5 javascript generics types object typescript

在打字稿中,我可以这样声明一个泛型函数:

const fn: <T>(arg: T)=>Partial<T>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,TypeScript有时可以根据我传递给它的实际参数来推断函数的类型参数。有没有类似的方法来定义可以根据其内容动态推断其类型参数的泛型对象文字?就像是:

interface XYZ { 
  obj: <T>{ arr: T[], dict: Partial<T> }
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以使整个接口通用,如下所示:

interface XYZ<T> {
  arr: T[],
  dict: Partial<T>
}
Run Code Online (Sandbox Code Playgroud)

但我想避免这种情况,因为那时我每次使用接口时都必须提前声明泛型。例如

const x: XYZ
Run Code Online (Sandbox Code Playgroud)

不管用。如果要使该声明具有一般性,则必须写:

const x: XYZ<any>
Run Code Online (Sandbox Code Playgroud)

但这不允许TypeScript根据以下内容的实际内容动态推断特定的泛型类型: x

jca*_*alz 8

啊,您需要Microsoft/TypeScript#17574 中讨论的通用值。正如您所注意到的,除了泛型函数之外,它们不存在于语言中。如果你愿意,你可以去解决这个问题,或者如果你认为它有帮助,可以讨论你的用例。

鉴于通用接口

interface XYZ<T> {
  arr: T[],
  dict: Partial<T>
}
Run Code Online (Sandbox Code Playgroud)

我只会使用这种解决方法:创建一个通用函数来验证某个值是否XYZ<T>适用于some T,并允许类型推断T在必要时进行实际推断。永远不要尝试声明 type 的东西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}>
Run Code Online (Sandbox Code Playgroud)

以上通常在实践中对我有用。优点是它是“自然的”TypeScript。缺点是它不能正确代表“我不在乎是什么类型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);
Run Code Online (Sandbox Code Playgroud)

SomeXYZ类型是一种不再关心 的具体类型T,但持有XYZ<T>某些T的引用。您使用asSomeXYZ从对象创建一个:

const someXYZ: SomeXYZ = asSomeXYZ({
  arr: [{ a: 1, b: 2 }, { a: 3, b: 4 }],
  dict: { a: 1300 }
}); // SomeXYZ
Run Code Online (Sandbox Code Playgroud)

您可以通过传递一个处理持有的引用的函数来使用它。该函数必须XYZ<T>为 any做好准备T,因为您不知道正在持有什么类型的Ta SomeXYZ

// use one
const xyzArrLength = someXYZ((xyz => xyz.arr.length))
Run Code Online (Sandbox Code Playgroud)

xyzArrLengthnumber,因为该函数xyz => xyz.arr.length返回一个number不管是什么T是。

TypeScript 中的存在类型很尴尬,因为有很多控制反转。这是它的主要缺点,也是为什么我通常采用我首先提出的不太完美但更容易思考的解决方法。

希望有帮助。祝你好运!

编辑:重新阅读您的问题让我觉得您实际上是在寻求我列为“解决方法”的答案。所以,呃……用那个?干杯。