TypeScript中遍歷對(duì)象鍵的方法
前言
在日常的TypeScript開發(fā)中,經(jīng)常需要遍歷對(duì)象的鍵來執(zhí)行各種操作。然而,使用Object.keys時(shí)可能會(huì)遇到一些類型相關(guān)的困擾,因?yàn)樗祷氐氖且粋€(gè)字符串?dāng)?shù)組,而不是期望的鍵的聯(lián)合類型。這可能導(dǎo)致在代碼中引入一些不安全的類型轉(zhuǎn)換。在本文中,我們將深入研究這個(gè)問題,并提供幾種解決方案,以便在遍歷對(duì)象鍵時(shí)更安全、更靈活地操作。
背景
使用Object.keys進(jìn)行遍歷并不能按照預(yù)期工作。這是因?yàn)?code>Object.keys返回一個(gè)字符串?dāng)?shù)組,而不是包含所有鍵的聯(lián)合類型。這是設(shè)計(jì)上的考慮,不會(huì)改變。
function printUser(user: User) {
Object.keys(user).forEach((key) => {
// 不起作用!
console.log(user[key]);
// 報(bào)錯(cuò):屬性“key”在類型“User”上不存在。
});
}
在適當(dāng)?shù)奈恢眠M(jìn)行keyof typeof類型轉(zhuǎn)換可以解決這個(gè)問題:
const user = {
name: "Daniel",
age: 26,
};
const keys = Object.keys(user);
keys.forEach((key) => {
// 不再報(bào)錯(cuò)!
console.log(user[key as keyof typeof user]);
});
通過自定義類型斷言,可以在行內(nèi)縮小類型:
function isKey<T extends object>(
x: T,
k: PropertyKey
): k is keyof T {
return k in x;
}
keys.forEach((key) => {
if (isKey(user, key)) {
console.log(user[key]);
// key現(xiàn)在被縮小為 "name" | "age"
}
});
Object.keys
問題在于使用Object.keys似乎無法按照期望的方式工作。這是因?yàn)樗粫?huì)返回你需要的類型。
const user = {
name: "Daniel",
age: 26,
};
const keys = Object.keys(user);
// keys的類型是 string[]
這意味著你不能使用鍵來訪問對(duì)象上的值:
const nameKey = keys[0];
user[nameKey];
// 報(bào)錯(cuò):屬性“nameKey”在類型“{ name: string; age: number; }”上不存在。
TypeScript之所以返回字符串?dāng)?shù)組,是因?yàn)樗膶?duì)象類型是開放的。在許多情況下,TS無法保證由Object.keys返回的鍵實(shí)際上存在于對(duì)象上 - 因此將它們擴(kuò)展為字符串是唯一合理的解決方案。
For...in循環(huán)
如果嘗試使用for...in循環(huán),同樣會(huì)失敗,原因是鍵被推斷為字符串,就像Object.keys一樣。
function printUser(user: User) {
for (const key in user) {
console.log(user[key]);
// 報(bào)錯(cuò):屬性“key”在類型“User”上不存在。
}
}
但在許多情況下,你可能確信自己完全了解對(duì)象的形狀。
那么,怎么辦呢?
解決方案
解決方案1:轉(zhuǎn)換為keyof typeof
第一種選擇是使用keyof typeof將鍵轉(zhuǎn)換為更具體的類型。
const user = {
name: "Daniel",
age: 26,
};
const keys = Object.keys(user) as Array<keyof typeof user>;
keys.forEach((key) => {
// 不再報(bào)錯(cuò)!
console.log(user[key]);
});
在索引對(duì)象時(shí)也可以進(jìn)行轉(zhuǎn)換。
const keys = Object.keys(user);
keys.forEach((key) => {
console.log(user[key as keyof typeof user]);
});
然而,as在任何形式中通常是不安全的,這也不例外。
const user = {
name: "Daniel",
age: 26,
};
const nonExistentKey = "id" as keyof typeof user;
// 沒有錯(cuò)誤!
const value = user[nonExistentKey];
// as是一個(gè)強(qiáng)大的工具,它允許我們?cè)陬愋蜕掀垓_TypeScript。
解決方案2:類型斷言
通過使用isKey助手,可以在索引之前檢查鍵是否實(shí)際存在于對(duì)象中。
function isKey<T extends object>(
x: T,
k: PropertyKey
): k is keyof T {
return k in x;
}
keys.forEach((key) => {
if (isKey(user, key)) {
console.log(user[key]);
// key現(xiàn)在被縮小為 "name" | "age"
}
});
解決方案3:泛型函數(shù)
再來看一個(gè)略微奇怪的解決方案。在泛型函數(shù)內(nèi)部,使用in運(yùn)算符將類型縮小到鍵。
function printEachKey<T extends object>(obj: T) {
for (const key in obj) {
console.log(obj[key]);
// key的類型被縮小為Extract<keyof T, string>
}
}
// 每個(gè)鍵都被打印出來!
printEachKey({
name: "Daniel",
age: 26,
});
解決方案4:將Object.keys包裝在函數(shù)中
另一種解決方案是將Object.keys包裝在一個(gè)返回轉(zhuǎn)換類型的函數(shù)中。
const objectKeys = <T extends object>(obj: T) => {
return Object.keys(obj) as Array<keyof T>;
};
const keys = objectKeys({
name: "Daniel",
age: 26,
});
console.log(keys);
// keys的類型是("name" | "age")[]
這可能是最容易被濫用的解決方案 - 將轉(zhuǎn)換隱藏在函數(shù)中使其更有吸引力,可能導(dǎo)致人們?cè)诓豢紤]的情況下使用它。
結(jié)論
本文介紹了一些解決方案,從簡(jiǎn)單的類型轉(zhuǎn)換到更智能的類型謂詞,幫助我們更安全、更可靠地進(jìn)行對(duì)象鍵的遍歷。選擇哪種方法取決于項(xiàng)目的需求和個(gè)人偏好,但總體而言,通過了解這些技術(shù),我們可以更好地利用TypeScript的類型系統(tǒng),提高代碼的可維護(hù)性和安全性。
以上就是TypeScript中遍歷對(duì)象鍵的方法的詳細(xì)內(nèi)容,更多關(guān)于TypeScript遍歷對(duì)象鍵的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js仿蘋果iwatch外觀的計(jì)時(shí)器代碼分享
這篇文章主要介紹了JS+CSS3實(shí)現(xiàn)的類似于蘋果iwatch計(jì)時(shí)器特效,很實(shí)用的代碼,推薦給大家,有需要的小伙伴可以參考下。2015-08-08
微信小程序web-view無法打開該頁面不支持打開的解決方法
小程序現(xiàn)在日漸成熟,功能也越來越強(qiáng)大,我們今天來一起看看小程序跳轉(zhuǎn)的問題,下面這篇文章主要給大家介紹了關(guān)于微信小程序web-view無法打開該頁面不支持打開的解決方法,需要的朋友可以參考下2023-01-01
js 按照指定間隔 向字符串中插入隨機(jī)字符串的實(shí)現(xiàn)代碼
看到論壇有人問,覺得有意思,就試著寫了一下。2010-03-03
基于js實(shí)現(xiàn)抽紅包并分配代碼實(shí)例
這篇文章主要介紹了基于js實(shí)現(xiàn)抽紅包并分配代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
在javaScript中檢測(cè)數(shù)據(jù)類型的幾種方式小結(jié)
在用javaScript編程的過程中,我們經(jīng)常會(huì)遇到這樣一個(gè)問題,就是需要檢測(cè)一個(gè)數(shù)據(jù)或變量的類型,本篇文章主要介紹了在javaScript中檢測(cè)數(shù)據(jù)類型的幾種方式小結(jié),有興趣的可以了解一下。2017-03-03
document.open() 與 document.write()的區(qū)別
document.open() 與 document.write()的區(qū)別...2007-08-08

