本篇內(nèi)容主要講解“TypeScript高級(jí)類型有哪些及怎么用”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“TypeScript高級(jí)類型有哪些及怎么用”吧!
成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、平陰網(wǎng)絡(luò)推廣、小程序定制開(kāi)發(fā)、平陰網(wǎng)絡(luò)營(yíng)銷、平陰企業(yè)策劃、平陰品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供平陰建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:www.cdcxhl.com
前言
對(duì)于有 javascript 基礎(chǔ)的同學(xué)來(lái)說(shuō),入門 typescript 其實(shí)很容易,只需要簡(jiǎn)單掌握其基礎(chǔ)的類型系統(tǒng)就可以逐步將 js 應(yīng)用過(guò)渡到 ts 應(yīng)用。
// js const double = (num) => 2 * num // ts const double = (num: number): number => 2 * num
然而,當(dāng)應(yīng)用越來(lái)越復(fù)雜,我們很容易把一些變量設(shè)置為 any 類型,typescript 寫著寫著也就成了 anyscript。
在講解高級(jí)類型之前,我們需要先簡(jiǎn)單理解泛型是什么。
泛型是強(qiáng)類型語(yǔ)言中比較重要的一個(gè)概念,合理的使用泛型可以提升代碼的可復(fù)用性,讓系統(tǒng)更加靈活。下面是維基百科對(duì)泛型的描述:
泛型允許程序員在強(qiáng)類型程序設(shè)計(jì)語(yǔ)言中編寫代碼時(shí)使用一些以后才指定的類型,在實(shí)例化時(shí)作為參數(shù)指明這些類型。
泛型通過(guò)一對(duì)尖括號(hào)來(lái)表示( <>
),尖括號(hào)內(nèi)的字符被稱為 類型變量 ,這個(gè)變量用來(lái)表示類型。
function copy(arg: t): t { if (typeof arg === 'object') { return json.parse( json.stringify(arg) ) } else { return arg } }
這個(gè)類型 t,在沒(méi)有調(diào)用 copy 函數(shù)的時(shí)候并不確定,只有調(diào)用 copy 的時(shí)候,我們才知道 t 具體代表什么類型。
const str = copy('my name is typescript')
我們?cè)?vs code 中可以看到 copy 函數(shù)的參數(shù)以及返回值已經(jīng)有了類型,也就是說(shuō)我們調(diào)用 copy 函數(shù)的時(shí)候,給類型變量 t 賦值了 string。其實(shí),我們?cè)谡{(diào)用 copy 的時(shí)候可以省略尖括號(hào),通過(guò) ts 的類型推導(dǎo)是可以確定 t 為 string 的。
高級(jí)類型
除了 string、number、boolean 這種基礎(chǔ)類型外,我們還應(yīng)該了解一些類型聲明中的一些高級(jí)用法。
交叉類型(&)
交叉類型說(shuō)簡(jiǎn)單點(diǎn)就是將多個(gè)類型合并成一個(gè)類型,個(gè)人感覺(jué)叫做「合并類型」更合理一點(diǎn),其語(yǔ)法規(guī)則和邏輯 “與” 的符號(hào)一致。
t & u
假如,我現(xiàn)在有兩個(gè)類,一個(gè)按鈕,一個(gè)超鏈接,現(xiàn)在我需要一個(gè)帶有超鏈接的按鈕,就可以使用交叉類型來(lái)實(shí)現(xiàn)。
interface button { type: string text: string } interface link { alt: string href: string } const linkbtn: button & link = { type: 'danger', text: '跳轉(zhuǎn)到百度', alt: '跳轉(zhuǎn)到百度', href: 'http://www.baidu.com' }
聯(lián)合類型(|)
聯(lián)合類型的語(yǔ)法規(guī)則和邏輯 “或” 的符號(hào)一致,表示其類型為連接的多個(gè)類型中的任意一個(gè)。
t | u
例如,之前的 button 組件,我們的 type 屬性只能指定固定的幾種字符串。
interface button { type: 'default' | 'primary' | 'danger' text: string } const btn: button = { type: 'primary', text: '按鈕' }
類型別名(type)
前面提到的交叉類型與聯(lián)合類型如果有多個(gè)地方需要使用,就需要通過(guò)類型別名的方式,給這兩種類型聲明一個(gè)別名。類型別名與聲明變量的語(yǔ)法類似,只需要把 const
、 let
換成 type
關(guān)鍵字即可。
type alias = t | u
type innertype = 'default' | 'primary' | 'danger' interface button { type: innertype text: string } interface alert { type: buttontype text: string }
類型索引(keyof)
keyof
類似于 object.keys
,用于獲取一個(gè)接口中 key 的聯(lián)合類型。
interface button { type: string text: string } type buttonkeys = keyof button // 等效于 type buttonkeys = "type" | "text"
還是拿之前的 button 類來(lái)舉例,button 的 type 類型來(lái)自于另一個(gè)類 buttontypes,按照之前的寫法,每次 buttontypes 更新都需要修改 button 類,如果我們使用 keyof
就不會(huì)有這個(gè)煩惱。
interface buttonstyle { color: string background: string } interface buttontypes { default: buttonstyle primary: buttonstyle danger: buttonstyle } interface button { type: 'default' | 'primary' | 'danger' text: string } // 使用 keyof 后,buttontypes修改后,type 類型會(huì)自動(dòng)修改 interface button { type: keyof buttontypes text: string }
類型約束(extends)
這里的 extends
關(guān)鍵詞不同于在 class 后使用 extends
的繼承作用,泛型內(nèi)使用的主要作用是對(duì)泛型加以約束。我們用我們前面寫過(guò)的 copy 方法再舉個(gè)例子:
type basetype = string | number | boolean // 這里表示 copy 的參數(shù) // 只能是字符串、數(shù)字、布爾這幾種基礎(chǔ)類型 function copy(arg: t): t { return arg }
如果我們傳入一個(gè)對(duì)象就會(huì)有問(wèn)題。
extends
經(jīng)常與 keyof
一起使用,例如我們有一個(gè)方法專門用來(lái)獲取對(duì)象的值,但是這個(gè)對(duì)象并不確定,我們就可以使用 extends
和 keyof
進(jìn)行約束。
function getvalue(obj: t, key: k) { return obj[key] } const obj = { a: 1 } const a = getvalue(obj, 'a')
這里的 getvalue 方法就能根據(jù)傳入的參數(shù) obj 來(lái)約束 key 的值。
類型映射(in)
in
關(guān)鍵詞的作用主要是做類型的映射,遍歷已有接口的 key 或者是遍歷聯(lián)合類型。下面使用內(nèi)置的泛型接口 readonly
來(lái)舉例。
type readonly= { readonly [p in keyof t]: t[p]; }; interface obj { a: string b: string } type readonlyobj = readonly
我們可以結(jié)構(gòu)下這個(gè)邏輯,首先 keyof obj
得到一個(gè)聯(lián)合類型 'a' | 'b'
。
interface obj { a: string b: string } type objkeys = 'a' | 'b' type readonlyobj = { readonly [p in objkeys]: obj[p]; }
然后 p in objkeys
相當(dāng)于執(zhí)行了一次 foreach 的邏輯,遍歷 'a' | 'b'
type readonlyobj = { readonly a: obj['a']; readonly b: obj['b']; }
最后就可以得到一個(gè)新的接口。
interface readonlyobj { readonly a: string; readonly b: string; }
條件類型(u ? x : y)
條件類型的語(yǔ)法規(guī)則和三元表達(dá)式一致,經(jīng)常用于一些類型不確定的情況。
t extends u ? x : y
上面的意思就是,如果 t 是 u 的子集,就是類型 x,否則為類型 y。下面使用內(nèi)置的泛型接口 extract
來(lái)舉例。
type extract= t extends u ? t : never;
如果 t 中的類型在 u 存在,則返回,否則拋棄。假設(shè)我們兩個(gè)類,有三個(gè)公共的屬性,可以通過(guò) extract 提取這三個(gè)公共屬性。
interface worker { name: string age: number email: string salary: number } interface student { name: string age: number email: string grade: number } type commonkeys = extract// 'name' | 'age' | 'email'
工具泛型
typesscript 中內(nèi)置了很多工具泛型,前面介紹過(guò) readonly
、 extract
這兩種,內(nèi)置的泛型在 typescript 內(nèi)置的 lib.es5.d.ts
中都有定義,所以不需要任何依賴都是可以直接使用的。下面看看一些經(jīng)常使用的工具泛型吧。
partial
type partial= { [p in keyof t]?: t[p] }
partial
用于將一個(gè)接口的所有屬性設(shè)置為可選狀態(tài),首先通過(guò) keyof t
,取出類型變量 t
的所有屬性,然后通過(guò) in
進(jìn)行遍歷,最后在屬性后加上一個(gè) ?
。
我們通過(guò) typescript 寫 react 的組件的時(shí)候,如果組件的屬性都有默認(rèn)值的存在,我們就可以通過(guò) partial
將屬性值都變成可選值。
import react from 'react' interface buttonprops { type: 'button' | 'submit' | 'reset' text: string disabled: boolean onclick: () => void } // 將按鈕組件的 props 的屬性都改為可選 const render = (props: partial= {}) => { const baseprops = { disabled: false, type: 'button', text: 'hello world', onclick: () => {}, } const options = { ...baseprops, ...props } return ( ) }
required
type required= { [p in keyof t]-?: t[p] }
required
的作用剛好與 partial
相反,就是將接口中所有可選的屬性改為必須的,區(qū)別就是把 partial
里面的 ?
替換成了 -?
。
record
type record= { [p in k]: t }
record
接受兩個(gè)類型變量, record
生成的類型具有類型 k 中存在的屬性,值為類型 t。這里有一個(gè)比較疑惑的點(diǎn)就是給類型 k 加一個(gè)類型約束, extends keyof any
,我們可以先看看 keyof any
是個(gè)什么東西。
大致一直就是類型 k 被約束在 string | number | symbol
中,剛好就是對(duì)象的索引的類型,也就是類型 k 只能指定為這幾種類型。
我們?cè)跇I(yè)務(wù)代碼中經(jīng)常會(huì)構(gòu)造某個(gè)對(duì)象的數(shù)組,但是數(shù)組不方便索引,所以我們有時(shí)候會(huì)把對(duì)象的某個(gè)字段拿出來(lái)作為索引,然后構(gòu)造一個(gè)新的對(duì)象。假設(shè)有個(gè)商品列表的數(shù)組,要在商品列表中找到商品名為 「每日?qǐng)?jiān)果」的商品,我們一般通過(guò)遍歷數(shù)組的方式來(lái)查找,比較繁瑣,為了方便,我們就會(huì)把這個(gè)數(shù)組改寫成對(duì)象。
interface goods { id: string name: string price: string image: string } const goodsmap: record= {} const goodslist: goods[] = await fetch('server.com/goods/list') goodslist.foreach(goods => { goodsmap[goods.name] = goods })
pick
type pick= { [p in k]: t[p] }
pick
主要用于提取接口的某幾個(gè)屬性。做過(guò) todo 工具的同學(xué)都知道,todo工具只有編輯的時(shí)候才會(huì)填寫描述信息,預(yù)覽的時(shí)候只有標(biāo)題和完成狀態(tài),所以我們可以通過(guò) pick
工具,提取 todo 接口的兩個(gè)屬性,生成一個(gè)新的類型 todopreview。
interface todo { title: string completed: boolean description: string } type todopreview = pickconst todo: todopreview = { title: 'clean room', completed: false }
exclude
type exclude= t extends u ? never : t
exclude
的作用與之前介紹過(guò)的 extract
剛好相反,如果 t 中的類型在 u 不存在,則返回,否則拋棄?,F(xiàn)在我們拿之前的兩個(gè)類舉例,看看 exclude
的返回結(jié)果。
interface worker { name: string age: number email: string salary: number } interface student { name: string age: number email: string grade: number } type excludekeys = exclude// 'name' | 'age' | 'email'
取出的是 worker 在 student 中不存在的 salary
。
omit
type omit= pick< t, exclude >
omit
的作用剛好和 pick 相反,先通過(guò) exclude
先取出類型 t 中存在,但是 k 不存在的屬性,然后再由這些屬性構(gòu)造一個(gè)新的類型。還是通過(guò)前面的 todo 案例來(lái)說(shuō),todopreview 類型只需要排除接口的 description 屬性即可,寫法上比之前 pick 精簡(jiǎn)了一些。
interface todo { title: string completed: boolean description: string } type todopreview = omitconst todo: todopreview = { title: 'clean room', completed: false }
到此,相信大家對(duì)“TypeScript高級(jí)類型有哪些及怎么用”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!