<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          TypeScript 高級(jí)類型及用法

          共 13653字,需瀏覽 28分鐘

           ·

          2021-10-19 23:34


          點(diǎn)擊上方?前端瓶子君,關(guān)注公眾號(hào)

          回復(fù)算法,加入前端編程面試算法每日一題群

          本文詳細(xì)介紹了 TypeScript 高級(jí)類型的使用場(chǎng)景,對(duì)日常 TypeScript 的使用可以提供一些幫助。

          前言

          本文已收錄在 Github: github.com/beichensky/…[1] 中,走過(guò)路過(guò)點(diǎn)個(gè) Star 唄

          一、高級(jí)類型

          交叉類型(&)

          交叉類型是將多個(gè)類型合并為一個(gè)類型。這讓我們可以把現(xiàn)有的多種類型疊加到一起成為一種類型,它包含了所需的所有類型的特性。

          • 語(yǔ)法:T & U

            其返回類型既要符合 T 類型也要符合 U 類型

            • 用法:假設(shè)有兩個(gè)接口:一個(gè)是 Ant 螞蟻接口,一個(gè)是 Fly 飛翔接口,現(xiàn)在有一只會(huì)飛的螞蟻:
          interface?Ant?{
          ????name:?string;
          ????weight:?number;
          }

          interface?Fly?{
          ????flyHeight:?number;
          ????speed:?number;
          }

          //?少了任何一個(gè)屬性都會(huì)報(bào)錯(cuò)
          const?flyAnt:?Ant?&?Fly?=?{
          ????name:?'螞蟻呀嘿',
          ????weight:?0.2,
          ????flyHeight:?20,
          ????speed:?1,
          };
          復(fù)制代碼

          聯(lián)合類型(|)

          聯(lián)合類型與交叉類型很有關(guān)聯(lián),但是使用上卻完全不同。

          • 語(yǔ)法:T | U

            其返回類型為連接的多個(gè)類型中的任意一個(gè)

            • 用法:假設(shè)聲明一個(gè)數(shù)據(jù),既可以是 string 類型,也可以是 number 類型
          let?stringOrNumber:?string?|?number?=?0

          stringOrNumber?=?''
          復(fù)制代碼

          再看下面這個(gè)例子,start 函數(shù)的參數(shù)類型既是 Bird | Fish,那么在 start 函數(shù)中,想要直接調(diào)用的話,只能調(diào)用 BirdFish 都具備的方法,否則編譯會(huì)報(bào)錯(cuò)

          class?Bird?{
          ????fly()?{
          ????????console.log('Bird?flying');
          ????}
          ????layEggs()?{
          ????????console.log('Bird?layEggs');
          ????}
          }

          class?Fish?{
          ????swim()?{
          ????????console.log('Fish?swimming');
          ????}
          ????layEggs()?{
          ????????console.log('Fish?layEggs');
          ????}
          }

          const?bird?=?new?Bird();
          const?fish?=?new?Fish();

          function?start(pet:?Bird?|?Fish)?{
          ????//?調(diào)用?layEggs?沒(méi)問(wèn)題,因?yàn)?Bird?或者?Fish?都有?layEggs?方法
          ????pet.layEggs();

          ????//?會(huì)報(bào)錯(cuò):Property 'fly' does not exist on type 'Bird | Fish'
          ????//?pet.fly();

          ????//?會(huì)報(bào)錯(cuò):Property 'swim' does not exist on type 'Bird | Fish'
          ????//?pet.swim();
          }

          start(bird);

          start(fish);
          復(fù)制代碼

          二、關(guān)鍵字

          類型約束(extends)

          語(yǔ)法:T extends K

          這里的 extends 不是類、接口的繼承,而是對(duì)于類型的判斷和約束,意思是判斷 T 能否賦值給 K

          可以在泛型中對(duì)傳入的類型進(jìn)行約束

          const?copy?=?(value:?string?|?number):?string?|?number?=>?value

          //?只能傳入?string?或者?number
          copy(10)

          //?會(huì)報(bào)錯(cuò):Argument of type 'boolean' is not assignable to parameter of type 'string | number'
          //?copy(false)
          復(fù)制代碼

          也可以判斷 T 是否可以賦值給 U,可以的話返回 T,否則返回 never

          type?Exclude?=?T?extends?U???T?:?never;
          復(fù)制代碼

          類型映射(in)

          會(huì)遍歷指定接口的 key 或者是遍歷聯(lián)合類型

          interface?Person?{
          ????name:?string
          ????age:?number
          ????gender:?number
          }

          //?將?T?的所有屬性轉(zhuǎn)換為只讀類型
          type?ReadOnlyType?=?{
          ????readonly?[P?in?keyof?T]:?T
          }

          //?type?ReadOnlyPerson?=?{
          //?????readonly?name:?Person;
          //?????readonly?age:?Person;
          //?????readonly?gender:?Person;
          //?}
          type?ReadOnlyPerson?=?ReadOnlyType
          復(fù)制代碼

          類型謂詞(is)

          • 語(yǔ)法:parameterName is Type

            parameterName 必須是來(lái)自于當(dāng)前函數(shù)簽名里的一個(gè)參數(shù)名,判斷 parameterName 是否是 Type 類型。

          具體的應(yīng)用場(chǎng)景可以跟著下面的代碼思路進(jìn)行使用:

          看完聯(lián)合類型的例子后,可能會(huì)考慮:如果想要在 start 函數(shù)中,根據(jù)情況去調(diào)用 Birdfly 方法和 Fishswim 方法,該如何操作呢?

          首先想到的可能是直接檢查成員是否存在,然后進(jìn)行調(diào)用:

          function?start(pet:?Bird?|?Fish)?{
          ????//?調(diào)用?layEggs?沒(méi)問(wèn)題,因?yàn)?Bird?或者?Fish?都有?layEggs?方法
          ????pet.layEggs();

          ????if?((pet?as?Bird).fly)?{
          ????????(pet?as?Bird).fly();
          ????}?else?if?((pet?as?Fish).swim)?{
          ????????(pet?as?Fish).swim();
          ????}
          }
          復(fù)制代碼

          但是這樣做,判斷以及調(diào)用的時(shí)候都要進(jìn)行類型轉(zhuǎn)換,未免有些麻煩,可能會(huì)想到寫個(gè)工具函數(shù)判斷下:

          function?isBird(bird:?Bird?|?Fish):?boolean?{
          ????return?!!(bird?as?Bird).fly;
          }

          function?isFish(fish:?Bird?|?Fish):?boolean?{
          ????return?!!(fish?as?Fish).swim;
          }

          function?start(pet:?Bird?|?Fish)?{
          ????//?調(diào)用?layEggs?沒(méi)問(wèn)題,因?yàn)?Bird?或者?Fish?都有?layEggs?方法
          ????pet.layEggs();

          ????if?(isBird(pet))?{
          ????????(pet?as?Bird).fly();
          ????}?else?if?(isFish(pet))?{
          ????????(pet?as?Fish).swim();
          ????}
          }
          復(fù)制代碼

          看起來(lái)簡(jiǎn)潔了一點(diǎn),但是調(diào)用方法的時(shí)候,還是要進(jìn)行類型轉(zhuǎn)換才可以,否則還是會(huì)報(bào)錯(cuò),那有什么好的辦法,能讓我們判斷完類型之后,就可以直接調(diào)用方法,不用再進(jìn)行類型轉(zhuǎn)換呢?

          OK,肯定是有的,類型謂詞 is 就派上用場(chǎng)了

          • 用法:
          function?isBird(bird:?Bird?|?Fish):?bird?is?Bird?{
          ????return?!!(bird?as?Bird).fly
          }

          function?start(pet:?Bird?|?Fish)?{
          ????//?調(diào)用?layEggs?沒(méi)問(wèn)題,因?yàn)?Bird?或者?Fish?都有?layEggs?方法
          ????pet.layEggs();

          ????if?(isBird(pet))?{
          ????????pet.fly();
          ????}?else?{
          ????????pet.swim();
          ????}
          };
          復(fù)制代碼

          每當(dāng)使用一些變量調(diào)用 isFish 時(shí),TypeScript 會(huì)將變量縮減為那個(gè)具體的類型,只要這個(gè)類型與變量的原始類型是兼容的。

          TypeScript 不僅知道在 if 分支里 pet 是 Fish 類型;它還清楚在 else 分支里,一定不是 Fish 類型,一定是 Bird 類型

          待推斷類型(infer)

          可以用 infer P 來(lái)標(biāo)記一個(gè)泛型,表示這個(gè)泛型是一個(gè)待推斷的類型,并且可以直接使用

          比如下面這個(gè)獲取函數(shù)參數(shù)類型的例子:

          type?ParamType?=?T?extends?(param:?infer?P)?=>?any???P?:?T;

          type?FunctionType?=?(value:?number)?=>?boolean

          type?Param?=?ParamType;???//?type?Param?=?number

          type?OtherParam?=?ParamType;???//?type?Param?=?symbol
          復(fù)制代碼

          判斷 T 是否能賦值給 (param: infer P) => any,并且將參數(shù)推斷為泛型 P,如果可以賦值,則返回參數(shù)類型 P,否則返回傳入的類型

          再來(lái)一個(gè)獲取函數(shù)返回類型的例子:

          type?ReturnValueType?=?T?extends?(param:?any)?=>?infer?U???U?:?T;

          type?FunctionType?=?(value:?number)?=>?boolean

          type?Return?=?ReturnValueType;???//?type?Return?=?boolean

          type?OtherReturn?=?ReturnValueType<number>;???//?type?OtherReturn?=?number
          復(fù)制代碼

          判斷 T 是否能賦值給 (param: any) => infer U,并且將返回值類型推斷為泛型 U,如果可以賦值,則返回返回值類型 P,否則返回傳入的類型

          原始類型保護(hù)(typeof)

          • 語(yǔ)法:typeof v === "typename"typeof v !== "typename"

          用來(lái)判斷數(shù)據(jù)的類型是否是某個(gè)原始類型(numberstringbooleansymbol)并進(jìn)行類型保護(hù)

          "typename"必須是 "number", "string", "boolean"或 "symbol"。但是 TypeScript 并不會(huì)阻止你與其它字符串比較,語(yǔ)言不會(huì)把那些表達(dá)式識(shí)別為類型保護(hù)。

          看下面這個(gè)例子, print 函數(shù)會(huì)根據(jù)參數(shù)類型打印不同的結(jié)果,那如何判斷參數(shù)是 string 還是 number 呢?

          function?print(value:?number?|?string)?{
          ????//?如果是?string?類型
          ????//?console.log(value.split('').join(',?'))

          ????//?如果是?number?類型
          ????//?console.log(value.toFixed(2))
          }
          復(fù)制代碼

          有兩種常用的判斷方式:

          1. 根據(jù)是否包含 split 屬性判斷是 string 類型,是否包含 toFixed 方法判斷是 number 類型

            弊端:不論是判斷還是調(diào)用都要進(jìn)行類型轉(zhuǎn)換

          2. 使用類型謂詞 is

            弊端:每次都要去寫一個(gè)工具函數(shù),太麻煩了

          • 用法:這就到了 typeof 一展身手的時(shí)候了
          function?print(value:?number?|?string)?{
          ????if?(typeof?value?===?'string')?{
          ????????console.log(value.split('').join(',?'))
          ????}?else?{
          ????????console.log(value.toFixed(2))
          ????}
          }
          復(fù)制代碼

          使用 typeof 進(jìn)行類型判斷后,TypeScript 會(huì)將變量縮減為那個(gè)具體的類型,只要這個(gè)類型與變量的原始類型是兼容的。

          類型保護(hù)(instanceof)

          typeof 類似,不過(guò)作用方式不同,instanceof 類型保護(hù)是通過(guò)構(gòu)造函數(shù)來(lái)細(xì)化類型的一種方式。

          instanceof 的右側(cè)要求是一個(gè)構(gòu)造函數(shù),TypeScript 將細(xì)化為:

          • 此構(gòu)造函數(shù)的 prototype 屬性的類型,如果它的類型不為 any 的話
          • 構(gòu)造簽名所返回的類型的聯(lián)合

          還是以 類型謂詞 is 示例中的代碼做演示:

          最初代碼:

          function?start(pet:?Bird?|?Fish)?{
          ????//?調(diào)用?layEggs?沒(méi)問(wèn)題,因?yàn)?Bird?或者?Fish?都有?layEggs?方法
          ????pet.layEggs();

          ????if?((pet?as?Bird).fly)?{
          ????????(pet?as?Bird).fly();
          ????}?else?if?((pet?as?Fish).swim)?{
          ????????(pet?as?Fish).swim();
          ????}
          }
          復(fù)制代碼

          使用 instanceof 后的代碼:

          function?start(pet:?Bird?|?Fish)?{
          ????//?調(diào)用?layEggs?沒(méi)問(wèn)題,因?yàn)?Bird?或者?Fish?都有?layEggs?方法
          ????pet.layEggs();

          ????if?(pet?instanceof?Bird)?{
          ????????pet.fly();
          ????}?else?{
          ????????pet.swim();
          ????}
          }
          復(fù)制代碼

          可以達(dá)到相同的效果

          索引類型查詢操作符(keyof)

          • 語(yǔ)法:keyof T

          對(duì)于任何類型 Tkeyof T 的結(jié)果為 T 上已知的 公共屬性名聯(lián)合

          interface?Person?{
          ????name:?string;
          ????age:?number;
          }

          type?PersonProps?=?keyof?Person;?//?'name'?|?'age'
          復(fù)制代碼

          這里,keyof Person 返回的類型和 'name' | 'age' 聯(lián)合類型是一樣,完全可以互相替換

          • 用法:keyof 只能返回類型上已知的 公共屬性名
          class?Animal?{
          ????type:?string;
          ????weight:?number;
          ????private?speed:?number;
          }

          type?AnimalProps?=?keyof?Animal;?//?"type"?|?"weight"
          復(fù)制代碼

          例如我們經(jīng)常會(huì)獲取對(duì)象的某個(gè)屬性值,但是不確定是哪個(gè)屬性,這個(gè)時(shí)候可以使用 extends 配合 typeof 對(duì)屬性名進(jìn)行限制,限制傳入的參數(shù)只能是對(duì)象的屬性名

          const?person?=?{
          ????name:?'Jack',
          ????age:?20
          }

          function?getPersonValue<T?extends?keyof?typeof?person>(fieldName:?keyof?typeof?person)?{
          ????return?person[fieldName]
          }

          const?nameValue?=?getPersonValue('name')
          const?ageValue?=?getPersonValue('age')

          //?會(huì)報(bào)錯(cuò):Argument of type '"gender"' is not assignable to parameter of type '"name"?|?"age"'
          //?getPersonValue('gender')
          復(fù)制代碼

          索引訪問(wèn)操作符(T[K])

          • 語(yǔ)法:T[K]

          類似于 js 中使用對(duì)象索引的方式,只不過(guò) js 中是返回對(duì)象屬性的值,而在 ts 中返回的是 T 對(duì)應(yīng)屬性 P 的類型

          • 用法:
          interface?Person?{
          ????name:?string
          ????age:?number
          ????weight:?number?|?string
          ????gender:?'man'?|?'women'
          }

          type?NameType?=?Person['name']??//?string

          type?WeightType?=?Person['weight']??//?string?|?number

          type?GenderType?=?Person['gender']??//?"man"?|?"women"
          復(fù)制代碼

          三、映射類型

          只讀類型(Readonly)

          • 定義:
          type?Readonly?=?{
          ????readonly?[P?in?keyof?T]:?T[P];
          }
          復(fù)制代碼

          用于將 T 類型的所有屬性設(shè)置為只讀狀態(tài)。

          • 用法:
          interface?Person?{
          ????name:?string
          ????age:?number
          }

          const?person:?Readonly?=?{
          ????name:?'Lucy',
          ????age:?22
          }

          //?會(huì)報(bào)錯(cuò):Cannot assign to 'name' because it is a read-only property
          person.name?=?'Lily'
          復(fù)制代碼

          readonly 只讀, 被 readonly 標(biāo)記的屬性只能在聲明時(shí)或類的構(gòu)造函數(shù)中賦值,之后將不可改(即只讀屬性)

          只讀數(shù)組(ReadonlyArray)

          • 定義:
          interface?ReadonlyArray?{
          ????/**?Iterator?of?values?in?the?array.?*/
          ????[Symbol.iterator]():?IterableIterator;

          ????/**
          ?????*?Returns?an?iterable?of?key,?value?pairs?for?every?entry?in?the?array
          ?????*/

          ????entries():?IterableIterator<[number,?T]>;

          ????/**
          ?????*?Returns?an?iterable?of?keys?in?the?array
          ?????*/

          ????keys():?IterableIterator<number>;

          ????/**
          ?????*?Returns?an?iterable?of?values?in?the?array
          ?????*/

          ????values():?IterableIterator;
          }
          復(fù)制代碼

          只能在數(shù)組初始化時(shí)為變量賦值,之后數(shù)組無(wú)法修改

          • 使用:
          interface?Person?{
          ????name:?string
          }

          const?personList:?ReadonlyArray?=?[{?name:?'Jack'?},?{?name:?'Rose'?}]

          //?會(huì)報(bào)錯(cuò):Property 'push' does not exist on type 'readonly Person[]'
          //?personList.push({?name:?'Lucy'?})

          //?但是內(nèi)部元素如果是引用類型,元素自身是可以進(jìn)行修改的
          personList[0].name?=?'Lily'
          復(fù)制代碼

          可選類型(Partial)

          用于將 T 類型的所有屬性設(shè)置為可選狀態(tài),首先通過(guò) keyof T,取出類型 T 的所有屬性, 然后通過(guò) in 操作符進(jìn)行遍歷,最后在屬性后加上 ?,將屬性變?yōu)榭蛇x屬性。

          • 定義:
          type?Partial?=?{
          ????[P?in?keyof?T]?:?T[P];
          }
          復(fù)制代碼
          • 用法:
          interface?Person?{
          ????name:?string
          ????age:?number
          }

          //?會(huì)報(bào)錯(cuò):Type '{}' is missing the following properties from type 'Person': name, age
          //?let?person:?Person?=?{}

          //?使用?Partial?映射后返回的新類型,name?和?age?都變成了可選屬性
          let?person:?Partial?=?{}

          person?=?{?name:?'pengzu',?age:?800?}

          person?=?{?name:?'z'?}

          person?=?{?age:?18?}
          復(fù)制代碼

          必選類型(Required)

          Partial 的作用相反

          用于將 T 類型的所有屬性設(shè)置為必選狀態(tài),首先通過(guò) keyof T,取出類型 T 的所有屬性, 然后通過(guò) in 操作符進(jìn)行遍歷,最后在屬性后的 ? 前加上 -,將屬性變?yōu)楸剡x屬性。

          • 定義:
          type?Required?=?{
          ????[P?in?keyof?T]-?:?T[P];
          }
          復(fù)制代碼
          • 使用:
          interface?Person?{
          ????name?:?string
          ????age?:?number
          }

          //?使用?Required?映射后返回的新類型,name?和?age?都變成了必選屬性
          //?會(huì)報(bào)錯(cuò):Type '{}' is missing the following properties from type 'Required': name, age
          let?person:?Required?=?{}
          復(fù)制代碼

          提取屬性(Pick)

          • 定義:
          type?Pickextends?keyof?T>?=?{
          ????[P?in?K]:?T[P];
          }
          復(fù)制代碼

          T 類型中提取部分屬性,作為新的返回類型。

          • 使用:比如我們?cè)诎l(fā)送網(wǎng)絡(luò)請(qǐng)求時(shí),只需要傳遞類型中的部分屬性,就可以通過(guò) Pick 來(lái)實(shí)現(xiàn)。
          interface?Goods?{
          ????type:?string
          ????goodsName:?string
          ????price:?number
          }

          //?作為網(wǎng)絡(luò)請(qǐng)求參數(shù),只需要?goodsName?和?price?就可以
          type?RequestGoodsParams?=?Pick'goodsName'?|?'price'>
          //?返回類型:
          //?type?RequestGoodsParams?=?{
          //?????goodsName:?string;
          //?????price:?number;
          //?}
          const?params:?RequestGoodsParams?=?{
          ????goodsName:?'',
          ????price:?10
          }
          復(fù)制代碼

          排除屬性(Omit)

          • 定義:type Omit = Pick>

            Pick 作用相反,用于從 T 類型中,排除部分屬性

            • 用法:比如長(zhǎng)方體有長(zhǎng)寬高,而正方體長(zhǎng)寬高相等,所以只需要長(zhǎng)就可以,那么此時(shí)就可以用 Omit 來(lái)生成正方體的類型
          interface?Rectangular?{
          ????length:?number
          ????height:?number
          ????width:?number
          }

          type?Square?=?Omit'height'?|?'width'>
          //?返回類型:
          //?type?Square?=?{
          //?????length:?number;
          //?}

          const?temp:?Square?=?{?length:?5?}
          復(fù)制代碼

          摘取類型(Extract)

          • 語(yǔ)法:Extract

            提取 T 中可以 賦值U 的類型

          • 定義:type Extract = T extends U ? T : never;

            • 用法:
          type?T01?=?Extract<"a"?|?"b"?|?"c"?|?"d",?"a"?|?"c"?|?"f">;??//?"a"?|?"c"

          type?T02?=?Extract<string?|?number?|?(()?=>?void),?Function>;??//?()?=>?void
          復(fù)制代碼

          排除類型(Exclude)

          • 語(yǔ)法:Exclude

            Extract 用法相反,從 T 中剔除可以賦值給 U的類型

          • 定義:type Exclude = T extends U ? never : T

            • 用法:
          type?T00?=?Exclude<"a"?|?"b"?|?"c"?|?"d",?"a"?|?"c"?|?"f">;??//?"b"?|?"d"

          type?T01?=?Exclude<string?|?number?|?(()?=>?void),?Function>;??//?string?|?number
          復(fù)制代碼

          屬性映射(Record)

          • 定義:
          type?Recordextends?string?|?number?|?symbol,?T>?=?{
          ????[P?in?K]:?T;
          }
          復(fù)制代碼

          接收兩個(gè)泛型,K 必須可以是可以賦值給 string | number | symbol 的類型,通過(guò) in 操作符對(duì) K 進(jìn)行遍歷,每一個(gè)屬性的類型都必須是 T 類型

          • 用法:比如我們想要將 Person 類型的數(shù)組轉(zhuǎn)化成對(duì)象映射,可以使用 Record 來(lái)指定映射對(duì)象的類型
          interface?Person?{
          ????name:?string
          ????age:?number
          }

          const?personList?=?[
          ????{?name:?'Jack',?age:?26?},
          ????{?name:?'Lucy',?age:?22?},
          ????{?name:?'Rose',?age:?18?},
          ]

          const?personMap:?Record<string,?Person>?=?{}

          personList.map((person)?=>?{
          ????personMap[person.name]?=?person
          })
          復(fù)制代碼

          比如在傳遞參數(shù)時(shí),希望參數(shù)是一個(gè)對(duì)象,但是不確定具體的類型,就可以使用 Record 作為參數(shù)類型

          function?doSomething(obj:?Record<string,?any>)?{
          }
          復(fù)制代碼

          不可為空類型(NonNullable)

          • 定義:type NonNullable = T extends null | undefined ? never : T

          從 T 中剔除 nullundefinednever 類型,不會(huì)剔除 voidunknow 類型

          type?T01?=?NonNullable<string?|?number?|?undefined>;??//?string?|?number

          type?T02?=?NonNullable<(()?=>?string)?|?string[]?|?null?|?undefined>;??//?(()?=>?string)?|?string[]

          type?T03?=?NonNullable<{name?:?string,?age:?number}?|?string[]?|?null?|?undefined>;??//?{name?:?string,?age:?number}?|?string[]
          復(fù)制代碼

          構(gòu)造函數(shù)參數(shù)類型(ConstructorParameters)

          返回 class 中構(gòu)造函數(shù)參數(shù)類型組成的 元組類型

          • 定義:
          /**
          ?*?Obtain?the?parameters?of?a?constructor?function?type?in?a?tuple
          ?*/

          type?ConstructorParametersextends?new?(...args:?any)?=>?any>?=?T?extends?new?(...args:?infer?P)?=>?any???P?:?never;
          復(fù)制代碼
          • 使用:
          class?Person?{
          ????name:?string
          ????age:?number
          ????weight:?number
          ????gender:?'man'?|?'women'

          ????constructor(name:?string,?age:?number,?gender:?'man'?|?'women')?{
          ????????this.name?=?name
          ????????this.age?=?age;
          ????????this.gender?=?gender
          ????}
          }

          type?ConstructorType?=?ConstructorParameters<typeof?Person>??//??[name:?string,?age:?number,?gender:?"man"?|?"women"]

          const?params:?ConstructorType?=?['Jack',?20,?'man']
          復(fù)制代碼

          實(shí)例類型(InstanceType)

          獲取 class 構(gòu)造函數(shù)的返回類型

          • 定義:
          /**
          ?*?Obtain?the?return?type?of?a?constructor?function?type
          ?*/

          type?InstanceTypeextends?new?(...args:?any)?=>?any>?=?T?extends?new?(...args:?any)?=>?infer?R???R?:?any;
          復(fù)制代碼
          • 使用:
          class?Person?{
          ????name:?string
          ????age:?number
          ????weight:?number
          ????gender:?'man'?|?'women'

          ????constructor(name:?string,?age:?number,?gender:?'man'?|?'women')?{
          ????????this.name?=?name
          ????????this.age?=?age;
          ????????this.gender?=?gender
          ????}
          }

          type?Instance?=?InstanceType<typeof?Person>??//?Person

          const?params:?Instance?=?{
          ????name:?'Jack',
          ????age:?20,
          ????weight:?120,
          ????gender:?'man'
          }
          復(fù)制代碼

          函數(shù)參數(shù)類型(Parameters)

          獲取函數(shù)的參數(shù)類型組成的 元組

          • 定義:
          /**
          ?*?Obtain?the?parameters?of?a?function?type?in?a?tuple
          ?*/

          type?Parametersextends?(...args:?any)?=>?any>?=?T?extends?(...args:?infer?P)?=>?any???P?:?never;
          復(fù)制代碼
          • 用法:
          type?FunctionType?=?(name:?string,?age:?number)?=>?boolean

          type?FunctionParamsType?=?Parameters??//?[name:?string,?age:?number]

          const?params:??FunctionParamsType?=?['Jack',?20]
          復(fù)制代碼

          函數(shù)返回值類型(ReturnType)

          獲取函數(shù)的返回值類型

          • 定義:
          /**
          ?*?Obtain?the?return?type?of?a?function?type
          ?*/

          type?ReturnTypeextends?(...args:?any)?=>?any>?=?T?extends?(...args:?any)?=>?infer?R???R?:?any;
          復(fù)制代碼
          • 使用:
          type?FunctionType?=?(name:?string,?age:?number)?=>?boolean?|?string

          type?FunctionReturnType?=?ReturnType??//?boolean?|?string
          復(fù)制代碼

          四、總結(jié)

          • 高級(jí)類型

            用法描述
            &交叉類型,將多個(gè)類型合并為一個(gè)類型,交集
            \聯(lián)合類型,將多個(gè)類型組合成一個(gè)類型,可以是多個(gè)類型的任意一個(gè),并集
          • 關(guān)鍵字

            用法描述
            T extends U類型約束,判斷 T 是否可以賦值給 U
            P in T類型映射,遍歷 T 的所有類型
            parameterName is Type類型謂詞,判斷函數(shù)參數(shù) parameterName 是否是 Type 類型
            infer P待推斷類型,使用 infer 標(biāo)記類型 P,就可以使用待推斷的類型 P
            typeof v === "typename"原始類型保護(hù),判斷數(shù)據(jù)的類型是否是某個(gè)原始類型(numberstringbooleansymbol
            instanceof v類型保護(hù),判斷數(shù)據(jù)的類型是否是構(gòu)造函數(shù)的 prototype 屬性類型
            keyof索引類型查詢操作符,返回類型上已知的 公共屬性名
            T[K]索引訪問(wèn)操作符,返回 T 對(duì)應(yīng)屬性 P 的類型
          • 映射類型

            用法描述
            Readonly將 T 中所有屬性都變?yōu)橹蛔x
            ReadonlyArray返回一個(gè) T 類型的只讀數(shù)組
            ReadonlyMap返回一個(gè) T 和 U 類型組成的只讀 Map
            Partial將 T 中所有的屬性都變成可選類型
            Required將 T 中所有的屬性都變成必選類型
            Pick從 T 中摘取部分屬性
            Omit從 T 中排除部分屬性
            Exclude從 T 中剔除可以賦值給 U 的類型
            Extract提取 T 中可以賦值給 U 的類型
            Record返回屬性名為 K,屬性值為 T 的類型
            NonNullable從 T 中剔除 null 和 undefined
            ConstructorParameters獲取 T 的構(gòu)造函數(shù)參數(shù)類型組成的元組
            InstanceType獲取 T 的實(shí)例類型
            Parameters獲取函數(shù)參數(shù)類型組成的元組
            ReturnType獲取函數(shù)返回值類型

          寫在后面

          如果有寫的不對(duì)或不嚴(yán)謹(jǐn)?shù)牡胤剑瑲g迎大家能提出寶貴的意見(jiàn),十分感謝。

          如果喜歡或者有所幫助,歡迎 Star,對(duì)作者也是一種鼓勵(lì)和支持

          關(guān)于本文

          作者:暖生

          https://juejin.cn/post/6985296521495314445

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會(huì)很認(rèn)真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對(duì)你有幫助,在看」是最大的支持
          ?》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持
          瀏覽 22
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  性感欧美美女被操的视频 | 日韩A√视频 | 毛片电影在线香 | 男女操逼免费视频 | 一级特黄60分钟免费 |