TypeScript 高級(jí)類型

前言


之前一直使用的是 js 現(xiàn)在轉(zhuǎn)過(guò)來(lái)學(xué)習(xí) ts 的時(shí)候嘗到了 ts 對(duì)類型規(guī)范的很多好處孽查,相應(yīng)的 ts 的類型有時(shí)候也讓人頭大,下面簡(jiǎn)單總結(jié)一下自己對(duì) ts 高級(jí)類型的學(xué)習(xí)成果茸苇。

一般類型


//給變量指定類型
const value: string = "value"
//給方法的形參和返回值指定類型
const fun0 = (str: string): string => {
    return ""
}
//甚至可以直接給方法指定類型
type funType = (str: string) => string
const fun1: funType = (str) => {
    return ""
}

這個(gè)時(shí)候我們可以看的 fun1 這時(shí)候是不用指定 str 的類型的置济,IDE會(huì)自動(dòng)提示迂求,如下:

image

但還有個(gè)特殊的情況 fun1 的形參是可以不寫(xiě)的,比如:

type funType = (str: string) => string
const fun2: funType = () => {
    return "fun2 return value"
}
console.log(fun2("value"));

這樣是不會(huì)報(bào)錯(cuò)的虱肄,可是為什么呢距帅?我們明明指定了funType的形參有且是string,那大家肯定想問(wèn)真是為什么匾寝,抱歉我也不知道搬葬,哈哈哈!如果有知道的朋友希望能留言告知艳悔。這樣做的問(wèn)題是在fun2里面是拿不到傳入的形參的急凰,不知道是不是bug。

泛型


對(duì)就是它猜年,我個(gè)人來(lái)說(shuō)在學(xué)習(xí)和使用ts的途中最頭疼的就是泛型抡锈,ts中泛型的使用真的讓人頭暈眼花,但當(dāng)你真的看明白ts中泛型的使用是又不得不說(shuō)這簡(jiǎn)直就像是在變魔術(shù)乔外。下面記錄一下泛型的一般用法:

//將對(duì)象中值為number類型的數(shù)據(jù)組成一個(gè)新對(duì)象
function getObjAllNum<T>(t: T): any {
    let numObj = {} as any;
    for (const tKey in t) {
        if (typeof t[tKey] == "number") {
            numObj[tKey] = t[tKey]
        }
    }
    return numObj
}
const value = {
    name: 'zl',
    age: 27,
    sex: 'm'
}
//輸出 {age: 27}
console.log(getObjAllNum(value));

可以看到床三,當(dāng)我們調(diào)用getObjAllNum的時(shí)候T類型已經(jīng)轉(zhuǎn)變成對(duì)象value的類型了。

image.png

高級(jí)類型


接下來(lái)要說(shuō)的就是ts為我們提供的一些類型的高級(jí)操作方式

類型別名(type)

可以理解成可以給一個(gè)類型再取另一個(gè)名字杨幼,比如:

type myString = string
const str: myString = "str"

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

A|B表示A或者B中的任意一個(gè)類型 撇簿,如下代碼,zhangSan就是屬于Man類型差购,xiaoLi屬于Woman類型四瘫。

interface Man {
    working(): void;
}
interface Woman {
    shopping(): void;
}
type Person = Man | Woman
const zhangSan: Person = {
    working() {
        console.log('working')
    }
}
zhangSan.working()
const xiaoLi: Person = {
    shopping() {
        console.log('shopping')
    }
}
xiaoLi.shopping()

但需要注意的是下面這種寫(xiě)法:

const person: Person = {
    working() {
        console.log('working')
    },
    shopping() {
        console.log('shopping')
    }
}

這樣寫(xiě)是不會(huì)報(bào)錯(cuò)的,但是當(dāng)試圖調(diào)用方法的時(shí)候就會(huì)報(bào)錯(cuò)欲逃,可以看出調(diào)用shopping的時(shí)候找蜜,就會(huì)提示Man不存在shopping屬性,其實(shí)這是因?yàn)?code>A|B聯(lián)合類型表示的是A或者B中的任意一個(gè)類型稳析,只有一個(gè)類型洗做,而不是兩種類型的合并弓叛,下面來(lái)說(shuō)說(shuō)真正的合并交叉類型(&)

image.png

交叉類型(&)

A&B高級(jí)類型是將兩個(gè)類型合并成了一個(gè)類型,這個(gè)類型擁有AB的所有屬性诚纸,所以稱其為合并類型也沒(méi)啥毛病邪码。這東西才學(xué)的時(shí)候一直以為是交集,其實(shí)應(yīng)該是并集才對(duì)咬清。

interface Apple {
    size: string,
    color: string,
}
interface Pen {
    type: string,
    color: string,
}
type Pineapple = Apple & Pen
const pineapple: Pineapple = {
    size: '大',
    color: '黃色',
    type: '海南鳳梨'
}

這里有個(gè)問(wèn)題就是兩個(gè)Interface做交叉類型時(shí)闭专,如果含有相同的key會(huì)出現(xiàn)什么問(wèn)題呢?詳情請(qǐng)見(jiàn)另一篇旧烧。

類型索引(keyof)

keyof的作用是將一個(gè)類型拆分開(kāi)了影钉,將拆分出來(lái)的子類型的集合作為類型返回,如下代碼掘剪,PersonKeys的類型(圖keyof.png所示)為name|age這種聯(lián)合類型

interface Person {
    name: string,
    age: number
}
type PersonKeys = keyof Person
keyof.png

類型約束(extends)

extends的作用是約束泛型平委,將泛型的類型限定成某個(gè)類型,如下例子:logPersonInfo<Person>()可以傳入ManWoman兩種類型夺谁,但logPersonInfo<Man>()卻只能傳入Man類型,logPersonInfo<Woman>()卻只能傳入Woman類型廉赔。

interface Person {
    name: string,
    age: number
}
class Man implements Person {
    name = 'zhangSan';
    age = 27;
    working() {}
}
class Woman implements Person {
    name = 'xiaoLi';
    age = 26;
    shopping() {}
}
function logPersonInfo<T extends Person>(t: T) {
    console.log(`name : ${t.name} , age : ${t.age}`)
}
logPersonInfo<Person>(new Man())
logPersonInfo<Person>(new Woman())
logPersonInfo<Man>(new Man())
logPersonInfo<Woman>(new Woman())

下面再說(shuō)一種情況,來(lái)更加深入的了解extends:

interface Person {
    name: string,
    age: number
}
class Alien {
    name = "E.T"
    age = 1000
    fly() {
    }
}
function logPersonInfo<T extends Person>(t: T) {
    console.log(`name : ${t.name} , age : ${t.age}`)
}
logPersonInfo<Person>(new Alien())

這個(gè)時(shí)候我們傳入logPersonInfo<Person>()的是一個(gè)Alien匾鸥,這時(shí)候也不會(huì)有什么問(wèn)題蜡塌,因?yàn)?code>Alien包含了Person的所有屬性。對(duì)比兩個(gè)例子我們能看得出來(lái)這里的extends和類繼承的extends是不一樣的勿负,這個(gè)地方的extends起到的作用只是限制泛型T的類型為包含了Person類型的所有屬性(當(dāng)然所有屬性的類型也要一致)的類型馏艾。

類型映射(in)

in高級(jí)類型起到的作用是做類型的映射,它會(huì)遍歷已有類型的所有key或者是聯(lián)合類型的所有類型奴愉,有點(diǎn)類似于forin琅摩。下面我們寫(xiě)的demo,將已有類型的所有屬性轉(zhuǎn)換成可空類型锭硼。

interface Person {
    name: string;
    age: number;
}
//此時(shí)這里的P就是in遍歷出來(lái)的key
//將Person的所有key遍歷出來(lái)設(shè)置成?:可空類型房资,再賦值上key對(duì)應(yīng)的value
//這時(shí)候的PersonValueCanNull類型就是所有屬性可為空的Person類型了
type PersonValueCanNull = { [P in keyof Person]?: Person[P] }

如上代碼,這個(gè)時(shí)候PersonValueCanNull的類型為{name?: string, age?: number},如圖:

image.png

再來(lái)個(gè)聯(lián)合類型的例子:

type ValueKeyType = "key1" | "key2" | "key3"
type ValueType = { [P in ValueKeyType]: boolean }
const value: ValueType = {
    key1: false,
    key2: false,
    key3: false,
}

結(jié)合上面聯(lián)合類型的例子檀头,我們?cè)賮?lái)看第一個(gè)例子轰异,[P in keyof Person]就可以拆分成[P in keyof "name"|"age"],其實(shí)最終都是使用聯(lián)合類型來(lái)進(jìn)行in操作

條件類型(A ? B : C)

條件類型其實(shí)就是一個(gè)三元運(yùn)算操作鳖擒,如果滿足條件A那么就是B類型溉浙,否則就是C類型,話不多說(shuō)上代碼:

//傳入T和U蒋荚,如果T包含U所有的key,那么返回類型是T馆蠕,反之返回的是T和U的交叉類型
type MergeAction<T, U> = T extends U ? T : T & U

interface Teacher {
    name: string,
    age: number,
    teachStudentNum: number
}

interface Father {
    name: string,
    age: number,
    childNum: number
}

//回顧一下之前的 extends期升, Teacher里面沒(méi)有包含F(xiàn)ather里面的
//所有key惊奇,所以返回的是Teacher&Father的交叉類型
const person: MergeAction<Teacher, Father> = {
    name: 'zl',
    age: 27,
    teachStudentNum: 60,
    childNum: 1
}

類型如圖:

image.png

下面我們?cè)賮?lái)個(gè)keyof的例子

const person :MergeAction<keyof Teacher, keyof Father> = "name"

此時(shí)的類型就是 name|age聯(lián)合類型了。

image.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末播赁,一起剝皮案震驚了整個(gè)濱河市颂郎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌容为,老刑警劉巖乓序,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異坎背,居然都是意外死亡替劈,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)得滤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)陨献,“玉大人,你說(shuō)我怎么就攤上這事懂更≌R担” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵沮协,是天一觀的道長(zhǎng)龄捡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)慷暂,這世上最難降的妖魔是什么墅茉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮呜呐,結(jié)果婚禮上就斤,老公的妹妹穿的比我還像新娘。我一直安慰自己蘑辑,他們只是感情好洋机,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著洋魂,像睡著了一般绷旗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上副砍,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天衔肢,我揣著相機(jī)與錄音,去河邊找鬼豁翎。 笑死角骤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播邦尊,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼背桐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蝉揍?” 一聲冷哼從身側(cè)響起链峭,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎又沾,沒(méi)想到半個(gè)月后弊仪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杖刷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年励饵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挺勿。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡曲横,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出不瓶,到底是詐尸還是另有隱情禾嫉,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布蚊丐,位于F島的核電站熙参,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏麦备。R本人自食惡果不足惜孽椰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凛篙。 院中可真熱鬧黍匾,春花似錦、人聲如沸呛梆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)填物。三九已至纹腌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滞磺,已是汗流浹背升薯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留击困,地道東北人涎劈。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親责语。 傳聞我的和親對(duì)象是個(gè)殘疾皇子炮障,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 在前端開(kāi)發(fā)中目派,大家入門(mén)ts其實(shí)是很簡(jiǎn)單的坤候,只要掌握一些基本的類型知識(shí)就可以逐步的將js過(guò)渡到ts的應(yīng)用,然而企蹭,當(dāng)我...
    mm_tang閱讀 1,577評(píng)論 0 1
  • 映射類型 一個(gè)常見(jiàn)的任務(wù)是將一個(gè)已知的類型每個(gè)屬性都變?yōu)榭蛇x的: interface PersonPartial ...
    2o壹9閱讀 1,530評(píng)論 1 49
  • 一白筹、交叉類型 交叉類型將多個(gè)類型合并為一個(gè)新的類型,新的具有所有參與合并的類型的特性谅摄,本質(zhì)上是一種并的操作徒河。形式如...
    kuxingseng686閱讀 530評(píng)論 0 0
  • 交叉類型 交叉類型將多個(gè)類型合并為一個(gè)類型,相當(dāng)于新類型具有這多個(gè)類型的所有特性送漠,相當(dāng)于是一種并的操作顽照,通常在使用...
    這個(gè)前端不太冷閱讀 667評(píng)論 0 0
  • 多態(tài)的 this類型 多態(tài)的 this類型表示的是某個(gè)包含類或接口的 子類型。 這被稱做 F-bounded多態(tài)性...
    2o壹9閱讀 521評(píng)論 1 50