摘要:斷言官方文檔中給出了這樣的解釋引入了一個(gè)名為斷言的字面值的新構(gòu)造。在中,標(biāo)準(zhǔn)做法是從名為的函數(shù)創(chuàng)建操作。如果我們有一個(gè)用于設(shè)置小時(shí)數(shù)組的類型,它可能看起來像這樣在之前,擴(kuò)展會(huì)使上述操作的字面量屬性更加通用,因?yàn)樗鼈兪强梢孕薷牡摹?/p>
翻譯:瘋狂的技術(shù)宅
blog.logrocket.com/const-asser…
我發(fā)現(xiàn)官方的 TypeScript 文檔非常有用,但是總覺得有點(diǎn)過于學(xué)術(shù)化并且枯燥無味。每當(dāng)我發(fā)現(xiàn)一個(gè)新功能時(shí),我想要知道這個(gè)功能究竟能夠解決什么問題而不是長篇大論。
在我看來,const assertions 是 TypeScript 3.4 的殺手級(jí)新功能,正如我稍后將要解釋的,我們可以用這個(gè)新功能省略很多繁瑣的類型聲明。
const 斷言const x = { text: "hello" } as const;
官方文檔中給出了這樣的解釋:
TypeScript 3.4 引入了一個(gè)名為 const 斷言的字面值的新構(gòu)造。它的語法是一個(gè)類型斷言,用 const 代替類型名稱(例如 123 as const)斷言構(gòu)造新的文字表達(dá)式時(shí),我們可以向語言發(fā)出以下信號(hào):
該表達(dá)式中的字面類型不應(yīng)被擴(kuò)展(例如:不能從“hello”轉(zhuǎn)換為字符串)
對象字面量獲取只讀屬性
數(shù)組文字成為只讀元組
感覺有點(diǎn)枯燥,還有點(diǎn)混亂。讓我們來各個(gè)擊破。
沒有類型擴(kuò)展的字面類型并不是每個(gè)人都知道類型擴(kuò)展,并且由于某些意外行為而首次發(fā)現(xiàn)它時(shí)都會(huì)覺得意外。
當(dāng)我們使用關(guān)鍵字 const 聲明一個(gè)字面量時(shí),類型是等號(hào)右邊的文字,例如:
const x = "x"; // x has the type "x"
const 關(guān)鍵字確保不會(huì)發(fā)生對變量進(jìn)行重新分配,并且只保證該字面量的嚴(yán)格類型。
但是如果我們用 let 而不是 const, 那么該變量會(huì)被重新分配,并且類型會(huì)被擴(kuò)展為字符串類型,如下所示:
let x = "x"; // x has the type string;
以下是兩個(gè)不同的聲明:
const x = "x"; // has the type "x"
let y = "x"; // has the type string
y 被擴(kuò)展為更通用的類型,并允許將其重新分配給該類型的其他值,而變量 x 只能具有 "x"的值。
用新的 const 功能,我可以這樣做:
let y = "x" as const; // y has type "x"`
對象字面量獲取只讀屬性
在 Typescript 3.4 之前,類型擴(kuò)展發(fā)生在對象字面量中:
const action = { type: "INCREMENT", } // has type { type: string }
即使我們將 action 聲明為 const,仍然可以重新分配 type 屬性,因此,該屬性被擴(kuò)展成了字符串類型。
這看上去令人覺得不是那么有用,所以讓我們換一個(gè)更好的例子。
如果你熟悉 Redux,就可能會(huì)發(fā)現(xiàn)上面的 action 變量可以用作 Redux action。如果你不知道 Redux 我來簡單解釋一下,Redux 是一個(gè)全局不可變的 state 存儲(chǔ)。通過向所謂的 reducers 發(fā)送動(dòng)作來修改狀態(tài)。 reducers 是純函數(shù),它在調(diào)度每個(gè) action 后返回全局狀態(tài)的新更新版本,以反映 acion 中指定的修改。
在 Redux 中,標(biāo)準(zhǔn)做法是從名為 action creators 的函數(shù)創(chuàng)建操作。 action creators 只是純函數(shù),它返回 Redux操作對象字面量以及提供給函數(shù)的所有參數(shù)。
用一個(gè)例子可以更好地說明這一點(diǎn)。應(yīng)用程序可能需要一個(gè)全局 count 屬性,為了更新這個(gè) count 屬性,我們可以調(diào)度類型為 "SET_COUNT" 的動(dòng)作,它只是將全局 count 屬性設(shè)置為一個(gè)新的值,這是一個(gè)字面對象屬性。這個(gè) action 的 action creator 將是一個(gè)函數(shù),它接受一個(gè)數(shù)字作為參數(shù),并返回一個(gè)具有屬性為 type、值為 SET_COUNT 和類型為 number 的 payload 屬性的對象,它將指定 count 的新值:
const setCount = (n: number) => {
return {
type: "SET_COUNT",
payload: n,
}
}
const action = setCount(3)
// action has type
// { type: string, payload: number }
從上面顯示的代碼中可以看出,type 屬性已經(jīng)被擴(kuò)展為 string 類型而不再是 SET_COUNT。這不是很安全的類型,我們可以保證的是 type 是一個(gè)字符串。 redux 中的每個(gè) action 都有一個(gè) type 屬性,它是一個(gè)字符串。
這不是很好,如果我們想要利用 type 屬性上的可區(qū)分聯(lián)合的話,那么在 TypeScript 3.4 之前,則需要為每個(gè) action 聲明一個(gè)接口或類型:
interface SetCount {
type: "SET_COUNT";
payload: number;
}
const setCount = (n: number): SetCount => {
return {
type: "SET_COUNT",
payload: n,
}
}
const action = setCount(3)
// action has type SetCount
這確實(shí)增加了編寫 Redux action 和 reducers 的負(fù)擔(dān),但我們可以通過添加一個(gè) const assertion 來解決這個(gè)問題:
const setCount = (n: number) => {
return <const>{
type: "SET_COUNT",
payload: n
}
}
const action = setCount(3);
// action has type
// { readonly type: "SET_COUNT"; readonly payload: number };
你會(huì)注意到從 setCount 推斷的類型已經(jīng)在每個(gè)屬性中附加了 readonly 修飾符,正如文檔的項(xiàng)目符號(hào)所述。
這就是所發(fā)生的事情:
{
readonly type: "SET_COUNT";
readonly payload: number
};
action 中的每個(gè)字面量都被添加了 readonly 修飾符。
在 redux 中,我們創(chuàng)建了一個(gè)接受 action 的聯(lián)合,reducer 函數(shù)可以通過這種操作來獲得良好的類型安全性。在 TypeScript 3.4 之前,我們會(huì)這樣做:
interface SetCount {
type: "SET_COUNT";
payload: number;
}
interface ResetCount {
type: "RESET_COUNT";
}
const setCount = (n: number): SetCount => {
return {
type: "SET_COUNT",
payload: n,
}
}
const resetCount = (): ResetCount => {
return {
type: "RESET_COUNT",
}
}
type CountActions = SetCount | ResetCount
我們創(chuàng)建了兩個(gè)接口 RESET_COUNT 和 SET_COUNT 來對兩個(gè) resetCount 和 setCount 的返回類型進(jìn)行歸類。
CountActions 是這兩個(gè)接口的聯(lián)合。
使用 const assertions,我們可以通過使用 const、 ReturnType 和 typeof 的組合來消除聲明這些接口的需要:
const setCount = (n: number) => {
return <const>{
type: "SET_COUNT",
payload: n
}
}
const resetCount = () => {
return <const>{
type: "RESET_COUNT"
}
}
type CountActions = ReturnType<typeof setCount> | ReturnType<typeof resetCount>;
我們從 action creator 函數(shù) setCount 和 resetCount 的返回類型中推斷出一個(gè)很好的 action 聯(lián)合。
數(shù)組字面量成為只讀元組在 TypeScript 3.4 之前,聲明一個(gè)字面量數(shù)組將被擴(kuò)展并且可以修改。
使用 const,我們可以將字面量鎖定為其顯式值,也不允許修改。
如果我們有一個(gè)用于設(shè)置小時(shí)數(shù)組的 redux action 類型,它可能看起來像這樣:
const action = {
type: "SET_HOURS",
payload: [8, 12, 5, 8],
}
// { type: string; payload: number[]; }
action.payload.push(12) // no error
在 TypeScript 3.4 之前,擴(kuò)展會(huì)使上述操作的字面量屬性更加通用,因?yàn)樗鼈兪强梢孕薷牡摹?/p>
如果我們將 const 應(yīng)用于對象字面量,那么就可以很好地控制所有內(nèi)容:
const action = <const>{
type: "SET_HOURS",
payload: [8, 12, 5, 8]
}
// {
// readonly type: "SET_HOURS";
// readonly payload: readonly [8, 12, 5, 8];
// }
action.payload.push(12); // error - Property "push" does not exist on type "readonly [8, 12, 5, 8]".
這里發(fā)生的事情恰恰是文檔的要點(diǎn):
payload 數(shù)組確實(shí)是 [8,12,5,8] 的“只讀”元組(不過我并沒有從文檔中看到這方面的說明)。
結(jié)論我用以下代碼總結(jié)以上所有內(nèi)容:
let obj = {
x: 10,
y: [20, 30],
z: {
a:
{ b: 42 }
}
} as const;
對應(yīng)于:
let obj: {
readonly x: 10;
readonly y: readonly [20, 30];
readonly z: {
readonly a: {
readonly b: 42;
};
};
};
在這里,我可以推斷出類型,而不是去編寫多余的樣板類型。這對于 redux 特別有用。
歡迎關(guān)注前端公眾號(hào):前端先鋒,獲取「前端工程化實(shí)用工具包」
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/6967.html
摘要:通常會(huì)定義為函數(shù)的返回值一個(gè)類型的變量是沒有生命用處的,因?yàn)轭愋偷淖兞恐荒苜x值為。和有一些區(qū)別的,函數(shù)沒有返回值時(shí)返回類型為的方法,即使沒有寫明語句,也會(huì)在函數(shù)執(zhí)行完的時(shí)候,隱式地返回一個(gè)類型。中新增加的變量聲明方式。 類型注解 類型注解使用 :TypeAnnotation 語法。類型聲明空間中可用的任何內(nèi)容都可以用作類型注解。 const num: number = 123; fun...
摘要:版本記錄針對版本的特性作專門的實(shí)例,希望能加深理解。這種情況下添加類型屬性被間接初始化了例如構(gòu)造函數(shù)中調(diào)用一個(gè)方法,更改了屬性的值。這種情況下我們可以使用顯式賦值斷言修飾符號(hào)來幫助類型系統(tǒng)識(shí)別類型。 TypeScript 2.7版本記錄 針對ts 2.7版本的特性作專門的實(shí)例,希望能加深理解。實(shí)例github地址 官方日志文檔 增加常量聲明的屬性的支持(Constant-named ...
摘要:比如或者都會(huì)導(dǎo)致函數(shù)返回值類型時(shí)。和特性一樣,等于是函數(shù)返回值中的或。注意對比下面的寫法對于,它的返回值是可迭代的對象,并且每個(gè)類型都是或者。首先是不支持方法重載的,是支持的,而類型系統(tǒng)一定程度在對標(biāo),當(dāng)然要支持這個(gè)功能。 1 引言 精讀原文是 typescript 2.0-2.9 的文檔: 2.0-2.8,2.9 草案. 我發(fā)現(xiàn),許多寫了一年以上 Typescript 開發(fā)者,對 T...
摘要:聯(lián)合類型,指賦值的時(shí)候可以是聯(lián)合類型中的某一個(gè)。任意屬性允許創(chuàng)建對象的時(shí)候,定義接口中沒有的屬性。常見的類型推論,還提現(xiàn)在函數(shù)表達(dá)式中。 typeScript是什么? TypeScript 是 JavaScript 的一個(gè)超集,主要提供了類型系統(tǒng)和對 ES6 的支持 安裝typeScript npm install -g typeScript 安裝完成查看版本: tsc -v typ...
摘要:怎么影響了我的思考方式對前端開發(fā)者來說,能強(qiáng)化了面向接口編程這一理念。使用的過程就是在加深理解的過程,確實(shí)面向接口編程天然和靜態(tài)類型更為親密。 電影《降臨》中有一個(gè)觀點(diǎn),語言會(huì)影響人的思維方式,對于前端工程師來說,使用 typescript 開發(fā)無疑就是在嘗試換一種思維方式做事情。 其實(shí)直到最近,我才開始系統(tǒng)的學(xué)習(xí) typescript ,前后大概花了一個(gè)月左右的時(shí)間。在這之前,我也在...
閱讀 3022·2021-11-23 09:51
閱讀 1016·2021-09-26 09:55
閱讀 3972·2021-09-22 14:58
閱讀 1504·2021-09-08 09:35
閱讀 1086·2021-08-26 14:16
閱讀 891·2019-08-23 18:17
閱讀 2073·2019-08-23 16:45
閱讀 710·2019-08-23 15:55