簡體   English   中英

TypeScript中對象文字的動態泛型類型推斷

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM