簡體   English   中英

使用對象文字的鍵作為 Typescript 類型?

[英]Using the keys of an object literal as a Typescript type?

我有一個對象,其中包含我的應用程序的一些預定義數據,它存儲在一個常量變量中,如下所示:

const data:{[key:string]:any} =Object.freeze({
    some: 123,
    long: {"a":"b"},
    list: ["c"],
    of: "",
    arbitrary: null,
    things: 1.2,
});

該對象的鍵對於應用程序的其余部分是已知的。 考慮這個訪問數據對象的函數:

function doWork(k) {
    if(!data.hasOwnProperty(k)) throw Error();
    let value = data[k];
    //...
}

這被稱為字符串

doWork("things");

我想用 Typescript 編譯時檢查替換無效鍵的運行時錯誤。 我希望能夠寫

function doWork(k: keyof data) {
    let value = data[k];
    //...
}

但顯然keyof運算符不能那樣工作。 我收到錯誤TS2304: Cannot find name 'data'.


我的解決方法:我可以用這樣的東西提取對象的鍵:

console.log("\""+Object.keys(data).join("\"|\"")+"\"");

然后我可以復制/粘貼並定義為類型。

type data_key = "some"|"long"|"list"|"of"|"arbitrary"|"things"
export function doWork(k:data_key) {
    let value = data[k];
    //...
}

這感覺就像一個愚蠢的 hack 並且每當我必須進行更改時都非常不方便,因為我必須記住將此語句放在正確的位置,運行程序,然后手動將值復制回源代碼(或實際上,只需自己輸入更改即可)。


我對更好的解決方案持開放態度。 是否有提供我正在尋找的功能的語言功能?

讓 TypeScript 推斷data的類型,然后使用type data_key = keyof typeof data;從它推斷的類型中提取鍵type data_key = keyof typeof data;

const data = Object.freeze({
    some: 123,
    long: {"a":"b"},
    list: ["c"],
    of: "",
    arbitrary: null,
    things: 1.2,
});

type data_key = keyof typeof data;

function doWork(k: data_key) {
    let value = data[k];
    //...
}

操場上。

它是如何工作的:

  1. TypeScript 具有高級類型推斷,因此能夠推斷傳遞給Object.freeze的對象初始值設定項的類型,鍵為somelonglist等。 Object.freeze被定義為freeze<T>(o: T): Readonly<T> ¹ 所以它返回相同推斷類型的Readonly版本。
  2. keyof獲取類型的鍵。
  3. typeof在這個上下文中是 TypeScript 的typeof ,而不是 JavaScript 的。 在 TypeScript 中,有些地方需要運行時值,有些地方需要編譯時類型。 keyof的操作數是需要編譯時類型的地方,因此typeof data返回編譯時類型的data ,這是從freeze推斷類型的只讀版本(鍵為somelonglist等.) (如果您有x = typeof data ,那么在需要運行時值的上下文中將是typeof ,因此它將是 JavaScript 的typeof ,而x將獲得運行時值"object" 。)

¹ lib.es5.d.ts中實際上有三種freeze定義(一種用於數組,一種用於函數,一種用於所有其他類型的對象;這是最后一種)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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