TS 其他類型的介紹與使用
二、高級類型
交叉類型, 聯合類型, 類型別名, 類型索引, 類型約束, 映射類型, 條件類型
交叉類型
通過 & 將多個類型合併爲一個類型,包含了所需的所有類型的特性,本質上是一種並的操作
K & Y
適用於對象合併場景,如下將聲明一個函數,將兩個對象合併成一個對象並返回:
function assign<K , Y>(one: K, two: Y) : K & Y {
let res: <K & Y> = {}
for (let key in one) {
res[key] = one[key]
}
for (let key in two) {
if(!res.hasOwnProperty(key)) {
res[key] = two[key]
}
}
return res
}
聯合類型
聯合類型的語法規則和邏輯 “或” 的符號一致,表示其類型爲連接的多個類型中的任意一個,本質上是一個交的關係
T | U
例如 number | string | boolean 的類型只能是這三個的一種,不能共存
如下所示:
function formatCommandline(command: string[] | string) {
let line = '';
if (typeof command === 'string') {
line = command.trim();
} else {
line = command.join(' ').trim();
}
}
類型別名
類型別名會給一個類型起個新名字,類型別名有時和接口很像,但是可以作用於原始值、聯合類型、元組以及其它任何你需要手寫的類型
可以使用 type SomeName = someValidTypeAnnotation 的語法來創建類型別名:
type some = boolean | string
const b: some = true // ok
const c: some = 'hello' // ok
const d: some = 123 // 不能將類型“123”分配給類型“some”
此外類型別名可以是泛型:
type Container<T> = { value: T };
也可以使用類型別名來在屬性裏引用自己:
type Tree<T> = {
value: T;
left: Tree<T>;
right: Tree<T>;
}
可以看到,類型別名和接口使用十分相似,都可以描述一個對象或者函數
兩者最大的區別在於,interface 只能用於定義對象類型,而 type 的聲明方式除了對象之外還可以定義交叉、聯合、原始類型等,類型聲明的方式適用範圍顯然更加廣泛
類型索引
keyof 類似於 Object.keys ,用於獲取一個接口中 Key 的聯合類型。
interface Ayong {
name: string
age: Number
}
const ayong={name:'ayong',age:18}
//這樣寫可以確定 key 的數據類型只能 是 Ayong類型中的
function getValue(key:keyof Ayong){
return ayong[key]
}
類型約束
通過關鍵字 extend 進行約束,不同於在 class 後使用 extends 的繼承作用,泛型內使用的主要作用是對泛型加以約束
Even 對象實例返回值類型 肯定是 Event, 但是我們想給 ev 添加屬性怎麼做?
以上寫法必然會報錯
我可以這樣做
interface Evt extends Event {//繼承基礎Event事件對象
name?: Sring;
}
function diyEvent(){
const evt :Evt = new Event('自定義事件')
evt.name = 'ayong'
}
類型約束通常和類型索引一起使用,例如我們有一個方法專門用來獲取對象的值,但是這個對象並不確定,我們就可以使用 extends 和 keyof 進行約束。
function getValue<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
const obj = { name: '阿勇' }
const name = getValue(obj, 'name')
以下是企業級項目中對 dom.addEventListener 事件監聽方法做了個上層封裝, 實際寫法如下
/**
* @param {Object} element Dom 節點 HTMLPictureElement
* @param {String} eventType 事件類型
* @param {Funtion} complete (e) 方法回掉
* @param {Boolean} useCapture true 冒泡觸發回掉 ,false冒泡觸發回掉
*/
function addEventListener<T extends EventTarget, E extends Event>({
element,
type,
handler
}: {
element: T;
type: string;
handler: (this: T, evt: E) => void;
}) {
element.addEventListener(type, handler as (evt: Event) => void);
}
映射類型
通過 in 關鍵字做類型的映射,遍歷已有接口的 key 或者是遍歷聯合類型,如下例子:
// 類型 ProKeys 有x/y/z,另一個類型Type1中也有x/y/z,並且Type1中的x/y/z類型相同
type ProKeys = 'x' | 'y' | 'z';
// 現在這種書寫方式相當於x/y/z重複書寫了兩次。
type Type1 = {x: number; y:number; z:number}
我們可以這樣做
type ProKeys = 'x' | 'y' | 'z';
type Type2 = {[Key in ProKeys]:number}
//映射類型相當於 一個類型枚遍歷舉 進行一一對應
條件類型
條件類型的語法規則和三元表達式一致,經常用於一些類型不確定的情況。
K extends T ? H : N
上面的意思就是,如果 K 是 T 的子集,就是類型 H,否則爲類型 N
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/5tflNaK2BpEKIll7j2ZydQ