JavaScript斷言與類(lèi)型守衛(wèi)及聯(lián)合聲明超詳細(xì)介紹
一、TypeScript 斷言
1.1 類(lèi)型斷言
個(gè)人理解的斷言,就是斷定某一個(gè)值的類(lèi)型,此時(shí)TypeScript以你所給出的值類(lèi)型為準(zhǔn),而非TypeScrip的推論
在一些復(fù)雜的類(lèi)型聲明 變成具體實(shí)現(xiàn)時(shí)往往用得到 并且避免很多類(lèi)型過(guò)于復(fù)雜的情況
類(lèi)型斷言有兩種形式:
1.尖括號(hào)語(yǔ)法
const someValue: any = "this is a string";
let strLength: number = (<{a:number}>someValue).a;2.as 語(yǔ)法
這個(gè)用的比較多
let someValue = "this is a string" as string; let strLength: number = someValue.length;
1.2 非空斷言
TypeScript 提供了一個(gè)特殊的語(yǔ)法,可以在不做任何檢查的情況下,從類(lèi)型中移除 null 和 undefined,這就是在任意表達(dá)式后面寫(xiě)上 ! ,這是一個(gè)有效的類(lèi)型斷言,表示它的值不可能是 null 或者 undefined:
1.3 確定賦值斷言
在 TypeScript 2.7 版本中引入了確定賦值斷言,即允許在實(shí)例屬性和變量聲明后面放置一個(gè) ! 號(hào),從而告訴 TypeScript 該屬性會(huì)被明確地賦值。為了更好地理解它的作用,我們來(lái)看個(gè)具體的例子:
let x: number; console.log(2 * x);
很明顯會(huì)有報(bào)錯(cuò),因?yàn)樵谫x值前使用變量,要解決該問(wèn)題,我們可以使用確定賦值斷言:
let x!: number; console.log(2 * x);
二、類(lèi)型守衛(wèi)
類(lèi)型保護(hù)是可執(zhí)行運(yùn)行時(shí)檢查的一種表達(dá)式,用于確保該類(lèi)型在一定的范圍內(nèi)。 換句話說(shuō),類(lèi)型保護(hù)可以保證一個(gè)字符串是一個(gè)字符串,盡管它的值也可以是一個(gè)數(shù)值。
如
//
function add(padding: number | string) {
return padding + 10; //運(yùn)算符“+”不能應(yīng)用于類(lèi)型“string | number”和“number”。
}
類(lèi)型保護(hù)與特性檢測(cè)并不是完全不同,其主要思想是嘗試檢測(cè)屬性、方法或原型,以確定如何處理值。目前主要有四種的方式來(lái)實(shí)現(xiàn)類(lèi)型保護(hù):
2.1 in關(guān)鍵字
js中的in 關(guān)鍵字 如果指定的屬性在指定的對(duì)象或其原型鏈中,則 in 運(yùn)算符返回 true。
const car = { make: 'Honda', model: 'Accord', year: 1998 };
console.log('make' in car); //true
delete car.make;
if ('make' in car === false) {
car.make = 'Suzuki';
}
console.log(car.make); //Suzukitypescript也是類(lèi)似的
interface Admin {
name: string;
privileges: string[];
}
interface Employee {
name: string;
startDate: Date;
}
type UnknownEmployee = Employee | Admin;
function printEmployeeInformation(emp: UnknownEmployee) {
console.log("Name: " + emp.name);
if ("privileges" in emp) {
console.log("Privileges: " + emp.privileges);
}
if ("startDate" in emp) {
console.log("Start Date: " + emp.startDate);
}
}2.2 typeof關(guān)鍵字
// “number”, “string”, “boolean” , “symbol”
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}typeof 類(lèi)型保護(hù)只支持兩種形式:typeof v === "typename" 和 typeof v !== typename,"typename" 必須是 "number", "string", "boolean" 或 "symbol"。 但是 TypeScript 并不會(huì)阻止你與其它字符串比較,語(yǔ)言不會(huì)把那些表達(dá)式識(shí)別為類(lèi)型保護(hù)。
2.3 instanceof 關(guān)鍵字
當(dāng)聯(lián)合類(lèi)型中使用的是 class 而不是 interface 時(shí),instanceof 語(yǔ)法就派上用場(chǎng)了,通過(guò) instanceof 語(yǔ)法可以區(qū)分不同的 class 類(lèi)型。
class Bird {
// 獨(dú)有方法
fly() {};
// 共有方法
layEggs() {};
}
class Fish {
// 獨(dú)有方法
swim() {};
// 共有方法
layEggs() {};
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // 正常
// 使用 in 語(yǔ)法進(jìn)行
if (pet instanceof Bird) {
pet.fly()
} else {
pet.swim()
} 2.4 **自定義類(lèi)型保護(hù)的類(lèi)型謂詞
function isNumber(x: any): x is number {
return typeof x === "number";
}
function isString(x: any): x is string {
return typeof x === "string";
}
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
if (pagination.pageSize != _pagination.pageSize && (<ListObjProps<T, K>>listProps).pagination?.pageSize) {
localStorage.setItem(FeManagePageSize, _pagination.pageSize?.toString() || '10')
}

三、聯(lián)合類(lèi)型和類(lèi)型別名
3.1 聯(lián)合類(lèi)型
聯(lián)合類(lèi)型通常與 null 或 undefined 一起使用:
const abc = (name: string | undefined) => {
};
例如,這里 name 的類(lèi)型是 string | undefined 意味著可以將 string 或 undefined 的值傳遞給abc 函數(shù)。
abc("semlinker");
abc(undefined);
通過(guò)這個(gè)示例,你可以憑直覺(jué)知道類(lèi)型 A 和類(lèi)型 B 聯(lián)合后的類(lèi)型是同時(shí)接受 A 和 B 值的類(lèi)型。此外,對(duì)于聯(lián)合類(lèi)型來(lái)說(shuō),你可能會(huì)遇到以下的用法:
let num: 1 | 2 = 1; type Type = 'click' | 'doubleClick' | 'mousemove';
3.2 可辨識(shí)聯(lián)合
TypeScript 可辨識(shí)聯(lián)合(Discriminated Unions)類(lèi)型,也稱(chēng)為代數(shù)數(shù)據(jù)類(lèi)型或標(biāo)簽聯(lián)合類(lèi)型。它包含 3 個(gè)要點(diǎn):可辨識(shí)、聯(lián)合類(lèi)型和類(lèi)型守衛(wèi)。
這種類(lèi)型的本質(zhì)是結(jié)合聯(lián)合類(lèi)型和字面量類(lèi)型的一種類(lèi)型保護(hù)方法。如果一個(gè)類(lèi)型是多個(gè)類(lèi)型的聯(lián)合類(lèi)型,且多個(gè)類(lèi)型含有一個(gè)公共屬性,那么就可以利用這個(gè)公共屬性,來(lái)創(chuàng)建不同的類(lèi)型保護(hù)區(qū)塊。
1. 可辨識(shí)
可辨識(shí)要求聯(lián)合類(lèi)型中的每個(gè)元素都含有一個(gè)單例類(lèi)型屬性,比如:
enum CarTransmission {
Automatic = 200,
Manual = 300
}
interface Motorcycle {
vType: "motorcycle";
make: number;
}
interface Car {
vType: "car";
transmission: CarTransmission
}
interface Truck {
vType: "truck";
capacity: number;
}在上述代碼中,我們分別定義了 Motorcycle、 Car 和 Truck 三個(gè)接口,在這些接口中都包含一個(gè) vType 屬性,該屬性被稱(chēng)為可辨識(shí)的屬性,而其它的屬性只跟特性的接口相關(guān)。
2. 聯(lián)合類(lèi)型
基于前面定義了三個(gè)接口,我們可以創(chuàng)建一個(gè) Vehicle 聯(lián)合類(lèi)型:
type Vehicle = Motorcycle | Car | Truck;
現(xiàn)在我們就可以開(kāi)始使用 Vehicle 聯(lián)合類(lèi)型,對(duì)于 Vehicle 類(lèi)型的變量,它可以表示不同類(lèi)型的車(chē)輛。
3. 類(lèi)型守衛(wèi)
下面我們來(lái)定義一個(gè) evaluatePrice 方法,該方法用于根據(jù)車(chē)輛的類(lèi)型、容量和評(píng)估因子來(lái)計(jì)算價(jià)格,具體實(shí)現(xiàn)如下:
const EVALUATION_FACTOR = Math.PI;
function evaluatePrice(vehicle: Vehicle) {
return vehicle.capacity * EVALUATION_FACTOR;
}
const myTruck: Truck = { vType: "truck", capacity: 9.5 };
evaluatePrice(myTruck);

原因是在 Motorcycle 接口中,并不存在 capacity 屬性,而對(duì)于 Car 接口來(lái)說(shuō),它也不存在 capacity 屬性。那么,現(xiàn)在我們應(yīng)該如何解決以上問(wèn)題呢?這時(shí),我們可以使用類(lèi)型守衛(wèi)。下面我們來(lái)重構(gòu)一下前面定義的 evaluatePrice 方法,重構(gòu)后的代碼如下:
function evaluatePrice(vehicle: Vehicle) {
switch(vehicle.vType) {
case "car":
return vehicle.transmission * EVALUATION_FACTOR;
case "truck":
return vehicle.capacity * EVALUATION_FACTOR;
case "motorcycle":
return vehicle.make * EVALUATION_FACTOR;
}
}
在以上代碼中,我們使用 switch 和 case 運(yùn)算符來(lái)實(shí)現(xiàn)類(lèi)型守衛(wèi),從而確保在 evaluatePrice 方法中,我們可以安全地訪問(wèn) vehicle 對(duì)象中的所包含的屬性,來(lái)正確的計(jì)算該車(chē)輛類(lèi)型所對(duì)應(yīng)的價(jià)格。
3.3 類(lèi)型別名
類(lèi)型別名用來(lái)給一個(gè)類(lèi)型起個(gè)新名字。
type Message = string | string[];
let greet = (message: Message) => {
};
ACTOR;
}
}在以上代碼中,我們使用 switch 和 case 運(yùn)算符來(lái)實(shí)現(xiàn)類(lèi)型守衛(wèi),從而確保在 evaluatePrice 方法中,我們可以安全地訪問(wèn) vehicle 對(duì)象中的所包含的屬性,來(lái)正確的計(jì)算該車(chē)輛類(lèi)型所對(duì)應(yīng)的價(jià)格。
到此這篇關(guān)于JavaScript斷言與類(lèi)型守衛(wèi)及聯(lián)合聲明超詳細(xì)介紹的文章就介紹到這了,更多相關(guān)JS斷言與類(lèi)型守衛(wèi)及聯(lián)合聲明內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript 高級(jí)語(yǔ)法之繼承的基本使用方法示例
這篇文章主要介紹了javascript 高級(jí)語(yǔ)法之繼承的基本使用方法,結(jié)合實(shí)例形式分析了JavaScript繼承的基本使用方法與操作注意事項(xiàng),需要的朋友可以參考下2019-11-11
符合W3C Web標(biāo)準(zhǔn)的圖片連續(xù)無(wú)間隙水平滾動(dòng)
很久以前就有這個(gè)問(wèn)題,總是找不到通用的,或比較簡(jiǎn)單的“圖片連續(xù)無(wú)間隙向左滾動(dòng),無(wú)間隙向右滾動(dòng),符合W3C Web標(biāo)準(zhǔn)”2008-06-06
javascript移動(dòng)開(kāi)發(fā)中touch觸摸事件詳解
這篇文章主要為大家詳細(xì)介紹了javascript移動(dòng)開(kāi)發(fā)中touch觸摸事件,感興趣的小伙伴們可以參考一下2016-03-03
JavaScript函數(shù)內(nèi)部屬性和函數(shù)方法實(shí)例詳解
函數(shù)是由事件驅(qū)動(dòng)的或者當(dāng)它被調(diào)用時(shí)執(zhí)行的可重復(fù)使用的代碼塊。通過(guò)本文給大家介紹JavaScript函數(shù)內(nèi)部屬性和函數(shù)方法,感興趣的朋友一起學(xué)習(xí)吧2016-03-03
javascript之通用簡(jiǎn)單的table選項(xiàng)卡實(shí)現(xiàn)(二)
上篇中的選項(xiàng)卡存在這樣的問(wèn)題:把邏輯封裝在table.js中,不夠靈活,也就是說(shuō)如果某個(gè)選項(xiàng)卡是實(shí)現(xiàn)異步請(qǐng)求或者跳轉(zhuǎn),而非div的顯隱切換,那么就得修過(guò)table.js來(lái)達(dá)到目的,顯然不是我所需要的。2010-05-05

