詳解TS對(duì)象擴(kuò)展運(yùn)算符和rest運(yùn)算符
概述
TypeScript 2.1 增加了對(duì) 對(duì)象擴(kuò)展運(yùn)算和 rest 屬性提案的支持,該提案在 ES2018 中標(biāo)準(zhǔn)化。可以以類型安全的方式使用 rest 和 spread 屬性。
對(duì)象 rest 屬性
假設(shè)已經(jīng)定義了一個(gè)具有三個(gè)屬性的簡(jiǎn)單字面量對(duì)象
const marius = {
name: "Marius Schulz",
website: "https://mariusschulz.com/",
twitterHandle: "@mariusschulz"
};
使用 ES6 解構(gòu)語法,可以創(chuàng)建幾個(gè)局部變量來保存相應(yīng)屬性的值。TypeScript 將正確地推斷每個(gè)變量的類型:
const { name, website, twitterHandle } = marius;
name; // Type string
website; // Type string
twitterHandle; // Type string
這些都是正確的,但這到現(xiàn)在也啥新鮮的。除了提取感興趣的一組屬性之外,還可以使用...語法將所有剩余的屬性收集到rest元素中:
const { twitterHandle, ...rest } = marius;
twitterHandle; // Type string
rest; // Type { name: string; website: string; }
TypeScript 會(huì)為得到結(jié)果的局部變量確定正確的類型。雖然twitterHandle變量是一個(gè)普通的字符串,但rest變量是一個(gè)對(duì)象,其中包含剩余兩個(gè)未被解構(gòu)的屬性。
對(duì)象擴(kuò)展屬性
假設(shè)咱們希望使用fetch()API 發(fā)出 HTTP 請(qǐng)求。它接受兩個(gè)參數(shù):一個(gè)URL和一個(gè)options對(duì)象,options包含請(qǐng)求的任何自定義設(shè)置。
在應(yīng)用程序中,可以封裝對(duì)fetch()的調(diào)用,并提供默認(rèn)選項(xiàng)和覆蓋給定請(qǐng)求的特定設(shè)置。這些配置項(xiàng)類似如下:
const defaultOptions = {
method: "GET",
credentials: "same-origin"
};
const requestOptions = {
method: "POST",
redirect: "follow"
};
使用對(duì)象擴(kuò)展,可以將兩個(gè)對(duì)象合并成一個(gè)新對(duì)象,然后傳遞給fetch()方法
// Type { method: string; redirect: string; credentials: string; }
const options = {
...defaultOptions,
...requestOptions
};
對(duì)象擴(kuò)展屬性創(chuàng)建一個(gè)新對(duì)象,復(fù)制defaultOptions中的所有屬性值,然后按照從左到右的順序復(fù)制requestOptions中的所有屬性值,最后得到的結(jié)果如下:
console.log(options);
// {
// method: "POST",
// credentials: "same-origin",
// redirect: "follow"
// }
請(qǐng)注意,分配順序很重要。如果一個(gè)屬性同時(shí)出現(xiàn)在兩個(gè)對(duì)象中,則后分配的會(huì)替換前面的。
當(dāng)然,TypeScript 理解這種順序。因此,如果多個(gè)擴(kuò)展對(duì)象使用相同的鍵定義一個(gè)屬性,那么結(jié)果對(duì)象中該屬性的類型將是最后一次賦值的屬性類型,因?yàn)樗采w了先前賦值的屬性:
const obj1 = { prop: 42 };
const obj2 = { prop: "Hello World" };
const result1 = { ...obj1, ...obj2 }; // Type { prop: string }
const result2 = { ...obj2, ...obj1 }; // Type { prop: number }
制作對(duì)象的淺拷貝
對(duì)象擴(kuò)展可用于創(chuàng)建對(duì)象的淺拷貝。假設(shè)咱希望通過創(chuàng)建一個(gè)新對(duì)象并復(fù)制所有屬性來從現(xiàn)有todo項(xiàng)創(chuàng)建一個(gè)新todo項(xiàng),使用對(duì)象就可以輕松做到:
const todo = {
text: "Water the flowers",
completed: false,
tags: ["garden"]
};
const shallowCopy = { ...todo };
實(shí)際上,你會(huì)得到一個(gè)新對(duì)象,所有的屬性值都被復(fù)制:
console.log(todo === shallowCopy);
// false
console.log(shallowCopy);
// {
// text: "Water the flowers",
// completed: false,
// tags: ["garden"]
// }
現(xiàn)在可以修改text屬性,但不會(huì)修改原始的todo項(xiàng):
hallowCopy.text = "Mow the lawn";
console.log(shallowCopy);
// {
// text: "Mow the lawn",
// completed: false,
// tags: ["garden"]
// }
console.log(todo);
// {
// text: "Water the flowers",
// completed: false,
// tags: ["garden"]
// }
但是,新的todo項(xiàng)引用與第一個(gè)相同的tags數(shù)組。由于是淺拷貝,改變數(shù)組將影響這兩個(gè)todo
shallowCopy.tags.push("weekend");
console.log(shallowCopy);
// {
// text: "Mow the lawn",
// completed: false,
// tags: ["garden", "weekend"]
// }
console.log(todo);
// {
// text: "Water the flowers",
// completed: false,
// tags: ["garden", "weekend"]
// }
如果想創(chuàng)建一個(gè)序列化對(duì)象的深拷貝,可以考慮使用jsON.parse(jsON.stringify(obj))或其他方法,如object.assign()。對(duì)象擴(kuò)展僅拷貝屬性值,如果一個(gè)值是對(duì)另一個(gè)對(duì)象的引用,則可能導(dǎo)致意外的行為。
keyof 和查找類型
JS 是一種高度動(dòng)態(tài)的語言。在靜態(tài)類型系統(tǒng)中捕獲某些操作的語義有時(shí)會(huì)很棘手。以一個(gè)簡(jiǎn)單的prop函數(shù)為例:
function prop(obj, key) {
return obj[key];
}
它接受一個(gè)對(duì)象和一個(gè)鍵,并返回相應(yīng)屬性的值。一個(gè)對(duì)象的不同屬性可以有完全不同的類型,咱們甚至不知道obj是什么樣子的。
那么如何在 TypeScript 中編寫這個(gè)函數(shù)呢?先嘗試一下:

有了這兩個(gè)類型注釋,obj必須是對(duì)象,key必須是字符串。咱們現(xiàn)在已經(jīng)限制了兩個(gè)參數(shù)的可能值集。然而,TS 仍然推斷返回類型為any:
const todo = {
id: 1,
text: "Buy milk",
due: new Date(2016, 11, 31)
};
const id = prop(todo, "id"); // any
const text = prop(todo, "text"); // any
const due = prop(todo, "due"); // any
如果沒有更進(jìn)一步的信息,TypeScript 就不知道將為key參數(shù)傳遞哪個(gè)值,所以它不能推斷出prop函數(shù)的更具體的返回類型。咱們需要提供更多的類型信息來實(shí)現(xiàn)這一點(diǎn)。
keyof 操作符號(hào)
在 JS 中屬性名稱作為參數(shù)的 API 是相當(dāng)普遍的,但是到目前為止還沒有表達(dá)在那些 API 中出現(xiàn)的類型關(guān)系。
TypeScript 2.1 新增加keyof操作符。輸入索引類型查詢或keyof,索引類型查詢keyof T產(chǎn)生的類型是T的屬性名稱。假設(shè)咱們已經(jīng)定義了以下Todo接口:
interface Todo {
id: number;
text: string;
due: Date;
}
各位可以將keyof操作符應(yīng)用于Todo類型,以獲得其所有屬性鍵的類型,該類型是字符串字面量類型的聯(lián)合
type TodoKeys = keyof Todo; // "id" | "text" | "due"
當(dāng)然,各位也可以手動(dòng)寫出聯(lián)合類型"id" | "text" | "due",而不是使用keyof,但是這樣做很麻煩,容易出錯(cuò),而且維護(hù)起來很麻煩。而且,它應(yīng)該是特定于Todo類型的解決方案,而不是通用的解決方案。
索引類型查詢
有了keyof,咱們現(xiàn)在可以改進(jìn)prop函數(shù)的類型注解。我們不再希望接受任意字符串作為key參數(shù)。相反,咱們要求參數(shù)key實(shí)際存在于傳入的對(duì)象的類型上
function prop <T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
TypeScript 現(xiàn)在以推斷prop函數(shù)的返回類型為T[K],這個(gè)就是所謂的索引類型查詢或查找類型。它表示類型T的屬性K的類型。如果現(xiàn)在通過prop方法訪問下面todo的三個(gè)屬性,那么每個(gè)屬性都有正確的類型:
const todo = {
id: 1,
text: "Buy milk",
due: new Date(2016, 11, 31)
};
const id = prop(todo, "id"); // number
const text = prop(todo, "text"); // string
const due = prop(todo, "due"); // Date
現(xiàn)在,如果傳遞一個(gè)todo對(duì)象上不存在的鍵會(huì)發(fā)生什么

編譯器會(huì)報(bào)錯(cuò),這很好,它阻止咱們?cè)噲D讀取一個(gè)不存在的屬性。
另一個(gè)真實(shí)的示例,請(qǐng)查看與TypeScript編譯器一起發(fā)布的lib.es2017.object.d.ts類型聲明文件中Object.entries()方法:
interface ObjectConstructor {
// ...
entries<T extends { [key: string]: any }, K extends keyof T>(o: T): [keyof T, T[K]][];
// ...
}
entries方法返回一個(gè)元組數(shù)組,每個(gè)元組包含一個(gè)屬性鍵和相應(yīng)的值。不可否認(rèn),在返回類型中有大量的方括號(hào),但是我們一直在尋找類型安全性。
以上就是詳解TS對(duì)象擴(kuò)展運(yùn)算符和rest運(yùn)算符的詳細(xì)內(nèi)容,更多關(guān)于TS對(duì)象擴(kuò)展運(yùn)算符和rest運(yùn)算符的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript使用Max函數(shù)返回兩個(gè)數(shù)字中較大數(shù)的方法
這篇文章主要介紹了JavaScript使用Max函數(shù)返回兩個(gè)數(shù)字中較大數(shù)的方法,涉及javascript中Max函數(shù)的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
JavaScript新引入的原始數(shù)據(jù)類型Symbol詳解
Symbol是ES6中引入的一種新的基本數(shù)據(jù)類型,用于表示一個(gè)獨(dú)一無二的值。它是JavaScript中的第七種數(shù)據(jù)類型。本文將詳細(xì)講講Symbol的使用,需要的可以參考一下2023-01-01
JS中把函數(shù)作為另一函數(shù)的參數(shù)傳遞方法(總結(jié))
下面小編就為大家?guī)硪黄狫S中把函數(shù)作為另一函數(shù)的參數(shù)傳遞方法(總結(jié))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06
JS實(shí)現(xiàn)根據(jù)當(dāng)前文字選擇返回被選中的文字
這篇文章主要介紹JS如何實(shí)現(xiàn)根據(jù)當(dāng)前文字選擇返回被選中的文字,需要的朋友可以參考下2014-05-05
JavaScript版經(jīng)典游戲之掃雷游戲完整示例【附demo源碼下載】
這篇文章主要介紹了JavaScript版經(jīng)典游戲之掃雷游戲?qū)崿F(xiàn)方法,結(jié)合完整實(shí)例形式分析了掃雷游戲的原理與具體實(shí)現(xiàn)流程,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2016-12-12
easyui window refresh 刷新兩次的解決方法(推薦)
下面小編就為大家?guī)硪黄猠asyui window refresh 刷新兩次的解決方法(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05

