keyof
類似于Object.keys()啥酱,用于把interface的所有key以“或”的形式組成一個(gè)新的類型蚌父,類似于枚舉類型
interface Point {
x: number;
y: number;
}
type PointKeys = keyof Point
const key: PointKeys = 'x' // key只能賦值'x'或者'y'
實(shí)例:實(shí)現(xiàn)一個(gè)get函數(shù)來(lái)獲取object的屬性值
function get<T extends Record<string, unknown>, K extends keyof T>(obj: T, key: K): T[K]{
return obj[key]
}
// 提示:使用Record<string, unknow>代替object
Record
上面用到了Record漱挚,那么就先來(lái)看它吧竣灌,通常用在聲明對(duì)象時(shí)進(jìn)行類型指定,第一個(gè)參數(shù)是key的類型,第二個(gè)參數(shù)是值得類型衩侥。
const obj: Record<string, string> = {
name: 'lisa'
}
Record實(shí)現(xiàn):這里又用到了keyof
type Record<K extends keyof any, T> = {
[P in K]: T
}
in
Record的實(shí)現(xiàn)中用到了in,in是與keyof相對(duì)應(yīng)的矛物,keyof是產(chǎn)生枚舉類型茫死,通過(guò)in可以遍歷枚舉類型
type Keys = 'a' | 'x' | 'y'
type Obj = {
[k in Keys]: unknow
}
==相當(dāng)于==> {a: unknow, x: unknow, y: unknow}
實(shí)例:提前看一下Partial源碼
type Partial<T> = {
[K in keyof T]?: T[K]
}
const obj: Partial<Point> = {
x: 1,
y: 1
}
// 因?yàn)閛bj類型相當(dāng)于{x?: number, y?: number}
Partial / Required / Readonly
說(shuō)到Partial,從源碼可以看出Partial用來(lái)將類型的所有屬性變?yōu)榭蛇x屬性履羞。
與其對(duì)應(yīng)的還有Required(將所有屬性變成必選)
type Required<T> = {
[K in keyof T]: T[K]
}
Readonly比較簡(jiǎn)單峦萎,就是把所有屬性變成只讀屬性
type C = {
x?: string
y: string
z: string
}
type aa = Readonly<C>
// 以上相當(dāng)于:
type aa = {
readonly x?: string;
readonly y: string;
readonly z: string;
}
實(shí)現(xiàn):
type Readonly<T> = {
readonly[K in keyof T]: T[K]
}
Pick / Omit
Pick:從接口中挑揀選擇部分屬性作為新的類型,第一個(gè)參數(shù):原接口類型忆首,第二個(gè)參數(shù):要選擇的屬性
type obj = {
a: number,
b: number,
x: number
}
const aa: Pick<obj, 'a'> = {
a: 1, // 只能有a屬性
}
實(shí)現(xiàn):
type Pick<T, K extends keyof T> = {
[P in K]: T[K]
}
Omit的作用是從接口中骨杂,忽略排除部分屬性作為新的類型。這里使用到了Exclude雄卷。如下:變量aa使用Omit聲明類型搓蚪,結(jié)果為obj中除了'a'和'x',剩下屬性=>{b: number}
type obj = {
a: number,
b: number,
x: number
}
const aa: Omit<obj, 'a' | 'x'> = {
b: 1,
}
實(shí)現(xiàn):
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
Exclude / Extract
Exclude字面意思就是“排除”丁鹉,從第一個(gè)參數(shù)類型中排除第二個(gè)參數(shù)中有的類型妒潭。
type A = 'x' | 'y'
type B = 'x' | 'y' | 'z'
type Oo = Exclude<B, A>
const str: Oo = 'z' // B的z類型在A中沒(méi)有,所以Exclude<B, A>就相當(dāng)于'z'
// const str: Oo = 'x' // 不可以賦值
實(shí)現(xiàn):
type Exclude<T, U> = T extends U ? never T
Extract和Exclude相對(duì)應(yīng)揣钦,用于取交集雳灾,即兩者都有的類型
type Ex = Extract<'id'|'name'|'age', 'id'|'ho'>
const obj: Ex = 'id'
const obj: Ex = 'ho' //報(bào)錯(cuò)
實(shí)現(xiàn):
type Exclude<T, U> = T extends U ? T : never
NonNullable
把聯(lián)合類型中的null和undefined去掉之后的新類型
type Test = number | null | undefined
type Non = NonNullable<Test> // 等價(jià)于 type Non = number
實(shí)現(xiàn):
type NonNullable<T> = T extends null | undefined ? never T
is類型保護(hù)
使用is可以做類型的保護(hù),常見(jiàn)實(shí)例如冯凹,isXXX函數(shù)谎亩,判定一個(gè)變量是不是指定類型。
function isStr(val: unknown): val is string {
return typeof val === 'string'
}
function fn(value: unknown){
if(isStr(value)){
console.log(value.length) // 這里value已經(jīng)判定為string類型宇姚,所有不會(huì)報(bào)錯(cuò)
}
}
fn(12)
如果不使用is匈庭,直接使用boolean
function isStr(val: unknown): boolean {
return typeof val === 'string'
}
function fn(value: unknown){
if(isStr(value)){
console.log(value.length) // 這里會(huì)報(bào)錯(cuò),因?yàn)関alue可能是unknow類型
}
}