TS中的一些關(guān)鍵詞總結(jié)
TS中的一些關(guān)鍵詞總結(jié)
最近一直在寫(xiě)TS,偶爾會(huì)遇到一些自己之前沒(méi)見(jiàn)過(guò)的一些符號(hào)或者關(guān)鍵詞,就隨手記錄下來(lái),本篇文章就是對(duì)這段時(shí)間遇到的進(jìn)行了總結(jié)。
目錄概覽
TS中的一些符號(hào)
!斷言操作符?.鏈判斷運(yùn)算符TS中的一些關(guān)鍵詞
typeinterfacetypeofkeyofinTS中的一些內(nèi)置類(lèi)型
Partial將類(lèi)型的屬性變成可選Required將類(lèi)型的屬性變成必選Pick從某個(gè)類(lèi)型中挑出一些屬性出來(lái)RecordMutable將類(lèi)型的屬性變成可修改Readonly類(lèi)型的屬性變成只讀ReturnType用來(lái)得到一個(gè)函數(shù)的返回值類(lèi)型
下面的一些例子都可以在 TypeScript Playground[1] 中進(jìn)行嘗試。左側(cè)是TS,右側(cè)是編譯后的JS。

TS中的一些符號(hào)
! 斷言操作符
! 的作用是斷言某個(gè)變量不會(huì)是 null/undefined,告訴編輯器停止報(bào)錯(cuò)。
const?obj?=?{
????name:?'牧碼的星星'
}
const?a?=?obj!.name;?//?假設(shè)?obj是你從后端獲取的獲取
確定 obj.name 一定是存在的且不是null/undefined,使用! 只是消除編輯器報(bào)錯(cuò),不會(huì)對(duì)運(yùn)行有任何影響。
屬性或者參數(shù)中使用 !,表示強(qiáng)制解析(告訴 typescript 編譯器,這里一定有值);
變量后使用 !: 表示類(lèi)型推薦排除 null/undefined。
?. 鏈判斷運(yùn)算符
const?orderId?=?response.result.data.orderId;
上面這種寫(xiě)法,很容易出現(xiàn)這種問(wèn)題 orderId is undefined,稍微有些經(jīng)驗(yàn)的我們立馬就能想到,肯定是代碼中 response.result.data 為 null 或者 undefined ,這樣,你肯定獲取不到 orderId。所以經(jīng)驗(yàn)豐富的我們?cè)谟龅将@取層級(jí)比較多的對(duì)象的時(shí)候,一般都是像下面這樣寫(xiě)。
//?正確的寫(xiě)法
const?orderId?=?(response
??&&?response.result
??&&?response.result.data
??&&?response.result.data.orderId)?||?'';
我們可以使用 ?. 來(lái)簡(jiǎn)化上面的代碼。
const?orderId?=?response?.result?.data?.orderId?||?'';
上面代碼使用了?.運(yùn)算符,直接在鏈?zhǔn)秸{(diào)用的時(shí)候判斷,左側(cè)的對(duì)象是否為null或undefined。如果是的,就不再往下運(yùn)算,而是返回undefined。
?. 支持如下語(yǔ)法
obj?.prop?//?對(duì)象屬性
obj?.[expr]?//?對(duì)象屬性
arr?.[index]?//?獲取數(shù)據(jù)中?index?下標(biāo)對(duì)應(yīng)的值
func?.(...args)?//?函數(shù)或?qū)ο蠓椒ǖ恼{(diào)用
?.和&&的區(qū)別
TS中的一些關(guān)鍵詞
type 類(lèi)型別名用來(lái)給一個(gè)類(lèi)型起個(gè)新名字
type?SetUser?=?(name:?string,?age:?number)?=>?void;
類(lèi)型別名常用于聯(lián)合類(lèi)型(聯(lián)合類(lèi)型表示取值可以為多種類(lèi)型中的一種),比如常見(jiàn)的如下寫(xiě)法
type?UploadType?=?'drag'?|?'select';
interface
interface 和 type 的用法其實(shí)差不多,interface 也是用來(lái)定義類(lèi)型的
interface?SetUser?=?{
????(name:?string,?age:?number)?=>?void;
}
type和interface的區(qū)別
都支持拓展,但是語(yǔ)法不同
interface?Name?{?
??name:?string;?
}
interface?User?extends?Name?{?
??age:?number;?
}
type?Name?=?{?
??name:?string;?
}
type?User?=?Name?&?{?age:?number??};
typeof 可以獲取一個(gè)變量的聲明類(lèi)型
在 JavaScript 中, typeof 可以判斷一個(gè)變量的基礎(chǔ)數(shù)據(jù)類(lèi)型, 在 TS 中,它還可以獲取一個(gè)變量的聲明類(lèi)型
const?obj?=?{?a:?'1'?};
type?Foo?=?typeof?obj;?
//?type?Foo?=?{?a:?string?}
keyof 可以獲取一個(gè)對(duì)象接口的所有 key 值
type?Obj?=?{?a:?string;?b:?string?}
type?Foo?=?keyof?obj;
//?type?Foo?=?'a'?|?'b';
in 可以遍歷枚舉類(lèi)型
type?Keys?=?'a'?|?'b'?|?'c';
type?Obj?=?{?
????[?T?in?Keys]:?string;
}
//?in?遍歷?Keys,并為每個(gè)值賦予?string?類(lèi)型
//?type?Obj?=?{
//?????a:?string,
//?????b:?string,
//?????c:?string
//?}
TS中一些內(nèi)置的類(lèi)型
官方文檔:https://www.typescriptlang.org/docs/handbook/utility-types.html#partialt
用到了上面提到的一些關(guān)鍵詞
Partial 將類(lèi)型的屬性變成可選
功能是將類(lèi)型的屬性變成可選,注意這是淺Partial
type?Partial?=?{?
????[P?in?keyof?T]?:?T[P]?
};
舉例說(shuō)明
interface?UserInfo?{
????id:?string;
????name:?string;
}
// error:Property 'id' is missing in type '{ name: string;?}' but required in type 'UserInfo'
const?xiaoming:?UserInfo?=?{
????name:?'xiaoming'
}
使用 ?Partial
type?NewUserInfo?=?Partial;
const?xiaoming:?NewUserInfo?=?{
????name:?'xiaoming'
}
這個(gè) ?NewUserInfo 就相當(dāng)于
interface?NewUserInfo?{
????id?:?string;
????name?:?string;
}
但是 Partial 有個(gè)局限性,就是只支持處理第一層的屬性,如果我的接口定義是這樣的
interface?UserInfo?{
????id:?string;
????name:?string;
????fruits:?{
????????appleNumber:?number;
????????orangeNumber:?number;
????}
}
type?NewUserInfo?=?Partial;
//?Property?'appleNumber'?is?missing?in?type?'{?orangeNumber:?number;?}'?but?required?in?type?'{?appleNumber:?number;?orangeNumber:?number;?}'.
const?xiaoming:?NewUserInfo?=?{
????name:?'xiaoming',
????fruits:?{
????????orangeNumber:?1,
????}
}
可以看到,第二層以后就不會(huì)處理了,如果要處理多層,就可以自己通過(guò) ?Conditional Types[2]
DeepPartial
type?DeepPartial?=?{
?????//?如果是?object,則遞歸類(lèi)型
????[U?in?keyof?T]?:?T[U]?extends?object
????????DeepPartial
??????:?T[U]
};
type?PartialedWindow?=?DeepPartial;?//?現(xiàn)在window?上所有屬性都變成了可選啦
Required將類(lèi)型的屬性變成必選
type?Required?=?{?
????[P?in?keyof?T]-?:?T[P]?
};
其中 -? 是代表移除 ? 這個(gè) modifier 的標(biāo)識(shí)。再拓展一下,除了可以應(yīng)用于 ? 這個(gè) modifiers ,還有應(yīng)用在 readonly ,比如 Readonly 這個(gè)類(lèi)型
type?Readonly?=?{
????readonly?[p?in?keyof?T]:?T[p];
}
Pick 從某個(gè)類(lèi)型中挑出一些屬性出來(lái)
type?Pick?=?{
????[P?in?K]:?T[P];
};
interface?UserInfo?{
????id:?string;
????name:?string;
}
type?NewUserInfo?=?Pick'name'>;?//?{name:?string;}
可以看到 NewUserInfo 中就只有個(gè) name 的屬性了。
Record
可以獲得根據(jù) K 中所有可能值來(lái)設(shè)置 key 以及 value 的類(lèi)型
type?Record?=?{
????[P?in?K]:?T;
};
舉個(gè)例子
type?CurRecord?=?Record<'a'?|?'b'?|?'c',?UserInfo>;?//?{?a:?UserInfo;?b:?UserInfo;?c:?UserInfo;?}
Mutable 將類(lèi)型的屬性變成可修改
功能是將類(lèi)型的屬性變成可修改,這里的 -指的是去除。-readonly 意思就是去除只讀,也就是可修改啦。
type?Mutable?=?{
??-readonly?[P?in?keyof?T]:?T[P];
};
Readonly 類(lèi)型的屬性變成只讀
type?Readonly?=?{?
????readonly?[P?in?keyof?T]:?T[P]?
};
ReturnType 用來(lái)得到一個(gè)函數(shù)的返回值類(lèi)型
type?ReturnType?any>?=?T?extends?(
??...args:?any[]
)?=>?infer?R
????R
??:?any;
infer在這里用于提取函數(shù)類(lèi)型的返回值類(lèi)型。ReturnType 只是將 infer R 從參數(shù)位置移動(dòng)到返回值位置,因此此時(shí) R 即是表示待推斷的返回值類(lèi)型。
下面的示例用ReturnType獲取到 Func 的返回值類(lèi)型為 string,所以,foo 也就只能被賦值為字符串了。
type?Func?=?(value:?number)?=>?string;
const?foo:?ReturnType?=?"1";
更多參考TS - es5.d.ts[3]
參考
細(xì)數(shù) TS 中那些奇怪的符號(hào)[4] TypeScript中高級(jí)應(yīng)用與最佳實(shí)踐[5] TS 中的內(nèi)置類(lèi)型簡(jiǎn)述[6] TypeScript 的工具類(lèi)型[7] 深入理解 TypeScript[8]
參考資料
TypeScript Playground: https://www.typescriptlang.org/play
[2]Conditional Types: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html
[3]TS - es5.d.ts: https://github.com/microsoft/TypeScript/blob/master/src/lib/es5.d.ts#L1431
[4]細(xì)數(shù) TS 中那些奇怪的符號(hào): https://segmentfault.com/a/1190000023943952
[5]TypeScript中高級(jí)應(yīng)用與最佳實(shí)踐: https://juejin.im/post/6844903904140853255#heading-9
[6]TS 中的內(nèi)置類(lèi)型簡(jiǎn)述: https://github.com/whxaxes/blog/issues/14
[7]TypeScript 的工具類(lèi)型: https://zhuanlan.zhihu.com/p/78180787
[8]深入理解 TypeScript: https://jkchao.github.io/typescript-book-chinese/
送書(shū)活動(dòng)
為了感謝各位小星星們一直以來(lái)對(duì) 【牧碼的星星】的大力支持和肯定,現(xiàn)在推出如下送抽獎(jiǎng)送書(shū)活動(dòng)。
