TypeScript 類型縮小的幾種實(shí)現(xiàn)方式
在 TypeScript 中,類型縮?。∟arrowing)是指根據(jù)特定條件將變量的類型細(xì)化為更具體的過程。它幫助開發(fā)者編寫更精確、更準(zhǔn)確的代碼,確保變量在運(yùn)行時(shí)只以符合其類型的方式進(jìn)行處理。
一、instanceof縮小類型
TypeScript 中的 instanceof 運(yùn)算符用于類型縮小,它允許我們檢查一個(gè)對(duì)象是否是特定類或構(gòu)造函數(shù)的實(shí)例。當(dāng)我們?cè)跅l件語(yǔ)句中使用 instanceof 時(shí),TypeScript 會(huì)根據(jù)檢查結(jié)果縮小變量的類型。
(一) 語(yǔ)法
if (objectToCheck instanceof ConstructorFunction) {
// 如果 objectToCheck 是 ConstructorFunction 的實(shí)例,則執(zhí)行此代碼塊
}其中:
- objectToCheck:是你想要檢查的對(duì)象,用于判斷它是否是某個(gè)特定類或構(gòu)造函數(shù)的實(shí)例。
- ConstructorFunction:是你要用來(lái)進(jìn)行檢查的構(gòu)造函數(shù)或類構(gòu)造器。如果 objectToCheck 是ConstructorFunction 的實(shí)例,該條件將為 true,TypeScript 會(huì)相應(yīng)地縮小 objectToCheck 的類型。
- instanceof:是一個(gè)用于類型縮小的關(guān)鍵字,它允許你檢查一個(gè)對(duì)象是否是特定類或構(gòu)造函數(shù)的實(shí)例。
(二) 用法舉例
1. 例一
在這個(gè)示例中,我們有兩個(gè)類:Car 和 Bicycle,它們各自擁有自己的方法(start 和 pedal)。
startVehicle 函數(shù)接受一個(gè)名為 vehicle 的參數(shù),該參數(shù)可以是 Car 或 Bicycle。
在函數(shù)內(nèi)部,我們使用 instanceof 來(lái)檢查 vehicle 的類型。
如果 vehicle 是 Car 的實(shí)例,類型將被縮小為 Car,從而可以調(diào)用 start 方法。
如果 vehicle 是 Bicycle 的實(shí)例,類型將被縮小為 Bicycle,從而可以調(diào)用 pedal 方法。
class Car {
start() {
console.log("Car started");
}
}
class Bicycle {
pedal() {
console.log("Bicycle pedaling");
}
}
function startVehicle(vehicle: Car | Bicycle) {
if (vehicle instanceof Car) {
// 在此代碼塊中,'vehicle' 的類型被縮小為 'Car'
vehicle.start();
} else {
// 在此代碼塊中,'vehicle' 的類型被縮小為 'Bicycle'
vehicle.pedal();
}
}
const myCar = new Car();
const myBicycle = new Bicycle();
startVehicle(myCar);
startVehicle(myBicycle);輸出:

2. 例二
在這個(gè)示例中,我們有一個(gè)類的繼承體系:Animal、Dog 和 Cat。
animalSound 函數(shù)接受一個(gè) Animal 類型的參數(shù)。
在函數(shù)內(nèi)部,我們使用 instanceof 檢查 animal 是否是 Dog 或 Cat 的實(shí)例。
如果是 Dog,animal 的類型被縮小為 Dog,我們可以調(diào)用其 speak 方法發(fā)出狗叫。
如果是 Cat,animal 的類型被縮小為 Cat,我們可以調(diào)用其 speak 方法發(fā)出貓叫。
否則,如果既不是 Dog 也不是 Cat,它仍然是 Animal 類型,我們調(diào)用通用的 speak 方法。
class Animal {
speak() {
console.log("Animal makes a sound");
}
}
class Dog extends Animal {
speak() {
console.log("Dog barks");
}
}
class Cat extends Animal {
speak() {
console.log("Cat meows");
}
}
function animalSound(animal: Animal) {
if (animal instanceof Dog) {
// 在此代碼塊中,'animal' 的類型被縮小為 'Dog'
animal.speak(); // 調(diào)用 Dog 的 speak 方法
} else if (animal instanceof Cat) {
// 在此代碼塊中,'animal' 的類型被縮小為 'Cat'
animal.speak(); // 調(diào)用 Cat 的 speak 方法
} else {
// 在此代碼塊中,'animal' 仍然是 'Animal' 類型
animal.speak(); // 調(diào)用 Animal 的 speak 方法
}
}
const dog = new Dog();
const cat = new Cat();
const genericAnimal = new Animal();
animalSound(dog);
animalSound(cat);
animalSound(genericAnimal);輸出:

二、typeof類型保護(hù)
在本節(jié)中,我們將學(xué)習(xí)關(guān)于 typeof 類型保護(hù)(type guards)中的類型縮小。TypeScript 是一種流行的編程語(yǔ)言,用于構(gòu)建可擴(kuò)展且健壯的應(yīng)用程序。在 TypeScript 中,typeof 類型保護(hù)允許你根據(jù) typeof 運(yùn)算符的結(jié)果縮小變量的類型。
這在處理諸如 string、number、boolean、symbol 和 undefined 等原始類型時(shí)特別有用,也可以用于檢查一個(gè)變量是否是函數(shù)(function)或?qū)ο螅╫bject)。
以下是 typeof 運(yùn)算符可以識(shí)別的類型:
- string
- number
- bigint
- boolean
- symbol
- undefined
- object
- function
(一) 語(yǔ)法
if (typeof variable === 'type') {
// 當(dāng)變量匹配指定類型時(shí)執(zhí)行的代碼
}其中:
typeof:這是 TypeScript 中用于檢查變量類型的運(yùn)算符。variable:是你想要檢查其類型的變量。'type':是表示你期望檢查的類型的字符串字面量。
(二) 用法舉例
1. 例一
你可以使用 typeof 來(lái)檢查一個(gè)變量是否是字符串類型。
const p = '2025 TypeScript Learning Guide';
if (typeof p === 'string') {
// 在這里,TypeScript 知道 'p' 是一個(gè)字符串。
console.log(p.toUpperCase());
}輸出:2025 TYPESCRIPT LEARNING GUIDE
2. 例二
你可以使用 typeof 來(lái)檢查一個(gè)變量是否是數(shù)字類型。
const age = 30;
if (typeof age === 'number') {
// TypeScript 知道 'age' 是一個(gè)數(shù)字。
console.log(age * 2);
}輸出:60
3. 例三
你可以使用 typeof 來(lái)檢查一個(gè)變量是否是布爾類型(boolean)。
const isActive = true;
if (typeof isActive === 'boolean') {
// TypeScript 知道 'isActive' 是一個(gè)布爾值。
console.log(isActive);
}輸出:false
4. 例四
你可以使用 typeof 來(lái)檢查一個(gè)變量是否是符號(hào)類型(symbol)。
const uniqueSymbol = Symbol('unique');
if (typeof uniqueSymbol === 'symbol') {
// TypeScript 知道 'uniqueSymbol' 是 symbol 類型。
console.log(uniqueSymbol.description);
}輸出:unique
5. 例五
你可以使用 typeof 來(lái)檢查一個(gè)變量是否是 undefined 類型。
let someValue;
if (typeof someValue === 'undefined') {
// TypeScript 知道
// 'someValue' 是 undefined 類型。
console.log('值是未定義的。');
}輸出:值是未定義的。
6. 例六
這個(gè)例子檢查了變量的類型是否為對(duì)象(typeof 為 "object"),但它不能區(qū)分不同的對(duì)象類型。它只能告訴你該變量不是其他基本類型之一。要更精確地判斷對(duì)象類型,可能需要使用其他類型保護(hù)手段,比如 instanceof 或者檢查對(duì)象是否存在某些特定屬性。
const person = {
name: 'FelixLu',
age: 30,
};
if (typeof person === 'object') {
console.log('person 是一個(gè)對(duì)象');
// 在這個(gè)代碼塊內(nèi),你可以安全地訪問 person 的屬性
console.log(`名字: ${person.name}, 年齡: ${person.age}`);
}輸出:
person 是一個(gè)對(duì)象
名字: FelixLu, 年齡: 30
7. 例七
你可以使用 typeof 來(lái)檢查一個(gè)變量是否是函數(shù)。
function greet() {
console.log('Hello!');
}
if (typeof greet === 'function') {
// TypeScript 知道 'greet' 是一個(gè)函數(shù)。
greet();
}輸出:Hello!
三、相等縮小類型
本節(jié)將介紹 TypeScript 中的“相等縮小類型”(Equality Narrowing Type)。
(一) 語(yǔ)法
TypeScript 是一種用于構(gòu)建可擴(kuò)展且健壯應(yīng)用程序的流行編程語(yǔ)言。在 TypeScript 中,“相等縮小”指的是根據(jù)相等性檢查或比較來(lái)縮小變量類型的過程。TypeScript 可以通過使用相等性檢查符號(hào)(===、==、!==、!=)或比較運(yùn)算符(<、>、<=、>=)來(lái)推斷更具體的類型,同時(shí)也可以利用 switch 語(yǔ)句實(shí)現(xiàn)類型縮小。
JavaScript 中較寬松的相等檢查(== 和 !=)也能被 TypeScript 正確縮小類型。如果你不熟悉,檢查某個(gè)值是否 == null 實(shí)際上不僅僅是判斷它是否為 null,還會(huì)判斷它是否可能是 undefined。同樣,== undefined 檢查的也是值是否為 null 或 undefined。
(二) 用法舉例
1. 例一
在這個(gè)例子中,我們有一個(gè) processValue 函數(shù),參數(shù) value 的類型是 number | string。在函數(shù)內(nèi)部,我們使用 typeof value === 'number' 來(lái)檢查 value 是否為數(shù)字類型。如果是,TypeScript 會(huì)在 if 代碼塊內(nèi)將 value 的類型縮小為 number,因此可以安全地對(duì)它執(zhí)行數(shù)值操作。在 else 代碼塊中,TypeScript 將 value 的類型縮小為 string,因?yàn)樗?value 不是數(shù)字(由 if 代碼塊的檢查排除),這樣你就可以安全地調(diào)用 toUpperCase() 方法。
function processValue(value: number | string): void {
if (typeof value === 'number') {
// 在這個(gè)代碼塊中,TypeScript
// 將 value 的類型縮小為 'number'
// 它知道 value 是數(shù)字類型
console.log(value + 10);
} else {
// 在這個(gè)代碼塊中,TypeScript
// 將 value 的類型縮小為 'string'
// 它知道 value 是字符串類型
console.log(value.toUpperCase());
}
}
// 使用示例:
processValue(5);
processValue('TypeScript');輸出:

2. 例二
這段示例中,我們定義了一個(gè) processArray 函數(shù),接受一個(gè)參數(shù) arr,其類型為 number[] 或 string[],表示它可以處理數(shù)字?jǐn)?shù)組或字符串?dāng)?shù)組。函數(shù)內(nèi)部通過 Array.isArray(arr) 檢查 arr 是否為數(shù)組。如果是,TypeScript 會(huì)在該 if 代碼塊中將 arr 的類型縮小為 number[] 或 string[]。
在 forEach 循環(huán)中,TypeScript 進(jìn)一步根據(jù)數(shù)組元素的類型縮小 item 的類型。如果 item 是數(shù)字,TypeScript 會(huì)識(shí)別它為數(shù)字類型;如果是字符串,則識(shí)別為字符串類型。這樣,我們就可以在循環(huán)內(nèi)安全地執(zhí)行針對(duì)數(shù)字或字符串的特定操作,而不會(huì)引發(fā)類型錯(cuò)誤。
當(dāng)我們用 numberArray 和 stringArray 調(diào)用 processArray 時(shí),TypeScript 會(huì)正確地縮小類型,并在函數(shù)內(nèi)進(jìn)行類型安全的操作。
function processArray(arr: number[] | string[]): void {
if (Array.isArray(arr)) {
// TypeScript 在此代碼塊中將 arr 的類型縮小為
// 'number[]' 或 'string[]'
arr.forEach((item) => {
if (typeof item === "number") {
// TypeScript 在這里將 item 的類型縮小為 'number'
console.log(`Number: ${item}`);
} else {
// TypeScript 在這里將 item 的類型縮小為 'string'
console.log(`String: ${item}`);
}
});
}
}
const numberArray: number[] = [1, 2, 3];
const stringArray: string[] = ["Typescript", "Java", "React"];
processArray(numberArray);
processArray(stringArray);輸出:

3. 例三
在這個(gè)例子中,printPersonInfo 函數(shù)接受一個(gè)類型為 Person 的參數(shù) person。Person 是一個(gè)接口,包含 name 屬性和一個(gè)可選的 age 屬性。函數(shù)內(nèi)部使用 in 操作符檢查 person 對(duì)象中是否存在 age 屬性。如果 age 屬性存在('age' in person 計(jì)算結(jié)果為 true),TypeScript 會(huì)在 if 代碼塊中縮小 person 的類型,使其包含 age 屬性。這樣我們就可以安全地訪問 person.age。如果 age 屬性不存在('age' in person 計(jì)算結(jié)果為 false),TypeScript 會(huì)在 else 代碼塊中縮小類型,排除 age 屬性。
interface Person {
name: string;
age?: number;
}
function printPersonInfo(person: Person) {
if ('age' in person) {
// 在此代碼塊中,'person' 被縮小為包含 'age' 屬性的類型
console.log(`Name: ${person.name}, Age: ${person.age}`);
} else {
// 在此代碼塊中,'person' 被縮小為不包含 'age' 屬性的類型
console.log(`Name: ${person.name}, Age not provided`);
}
}
const p1: Person = { name: 'FelixLu', age: 30 };
const p2: Person = { name: 'Felix' };
printPersonInfo(p1);
printPersonInfo(p2);輸出:

四、真值收窄類型
在本節(jié)中,我們將學(xué)習(xí) TypeScript 中的真值收窄類型(Truthiness Narrowing Type)。
TypeScript 是一種流行的編程語(yǔ)言,常用于構(gòu)建可擴(kuò)展且健壯的應(yīng)用程序。在 TypeScript 中,“真值收窄”是一種根據(jù)變量在條件語(yǔ)句中的真假值來(lái)縮小其類型的機(jī)制。這是一種類型推斷機(jī)制,利用了 JavaScript 中的“真值”(truthy)和“假值”(falsy)來(lái)確定變量可能的類型。
真值(Truthy Values):
在 JavaScript 中,被認(rèn)為是“真值”的值在布爾上下文中會(huì)被當(dāng)作 true 來(lái)處理。這些值包括:
- 非空字符串(如 "hello"、"true" 等)
- 非零數(shù)字(如 1、-42 等)
- 對(duì)象(包括數(shù)組和函數(shù))
- true
- 擁有 valueOf 方法并返回 true 的用戶自定義類的實(shí)例
假值(Falsy Values):
相反,被認(rèn)為是“假值”的值在布爾上下文中會(huì)被當(dāng)作 false 來(lái)處理。這些值包括:
- 空字符串("")
- 數(shù)字 0(0)
- null
- undefined
- false
- 0n(BigInt 類型的零)
- NaN(不是一個(gè)數(shù)字)
(一) 語(yǔ)法
if (condition) {
// 在這個(gè)代碼塊中,TypeScript 會(huì)收窄變量的類型。
} else {
// 在這個(gè)代碼塊中,TypeScript 會(huì)根據(jù)條件得知變量的不同類型信息。
}其中:
- condition:這是你希望檢查其“真值”或“假值”的表達(dá)式或變量。
- if 代碼塊中:TypeScript 會(huì)根據(jù)條件的真值情況收窄變量的類型。如果條件被認(rèn)為是 true,TypeScript 會(huì)相應(yīng)地收窄變量的類型。
- else 代碼塊中(可選):由于條件被判定為 false,TypeScript 會(huì)對(duì)變量有不同的類型推斷,與 if 塊中相反。
(二) 用法舉例
1. 例一
在 if 代碼塊中,TypeScript 將 name 的類型收窄為 string,因?yàn)樗鼨z查了 name 是否為真值(即不是 null 或 undefined)。
在 else 代碼塊中,TypeScript 理解 name 只能是 null 或 undefined,因?yàn)樗呀?jīng)在 if 中檢查過其為真值。
function greet(name: string | null) {
if (name) {
// 在這個(gè)代碼塊中,TypeScript 知道
// 'name' 是一個(gè)非 null 的字符串。
console.log(`Hello, ${name.toUpperCase()}!`);
} else {
// 在這個(gè)代碼塊中,TypeScript 知道
// 'name' 要么是 null,要么是 undefined。
console.log("Hello, TypeScript!");
}
}
greet("TypeScript");
greet(null);輸出:

2. 例二
在這個(gè)示例中,printType 函數(shù)接收一個(gè)參數(shù) value。在函數(shù)內(nèi)部,我們使用 typeof 來(lái)檢查 value 的類型。根據(jù)不同的類型,TypeScript 會(huì)在每個(gè) if 代碼塊中收窄 value 的類型。這使我們能夠安全地執(zhí)行與類型相關(guān)的操作。
function printType(value: any) {
if (typeof value === 'string') {
console.log("它是一個(gè)字符串:", value.toUpperCase());
} else if (typeof value === 'number') {
console.log("它是一個(gè)數(shù)字:", value.toFixed(2));
} else {
console.log("它是其他類型:", value);
}
}
printType("Hello, TypeScript!");
printType(42);
printType(true);輸出:

五、類型謂詞
在本文中,我們將學(xué)習(xí) TypeScript 中的類型謂詞。TypeScript 是一種靜態(tài)類型編程語(yǔ)言,提供了許多功能來(lái)使你的代碼更加高效和健壯。TypeScript 中的類型謂詞是返回布爾值的函數(shù),用于縮小變量的類型范圍。它們主要用于條件語(yǔ)句塊中,檢查變量是否屬于特定類型,然后據(jù)此執(zhí)行相應(yīng)的操作。類型謂詞可以使用 TypeScript 中的關(guān)鍵字 “is” 來(lái)定義。
(一) 語(yǔ)法
function is<TypeName>(variable: any): variable is TypeName {
// 返回布爾值
}在上面的語(yǔ)法中,TypeName 是你想要檢查的類型名稱,variable 是你想要縮小類型范圍的變量。is 關(guān)鍵字表示該函數(shù)返回一個(gè)布爾值,而 variable is TypeName 告訴 TypeScript,如果函數(shù)返回 true,那么該變量就是指定的類型。
(二) 用法舉例
1. 使用原始類型的類型謂詞
在這個(gè)示例中,我們將了解類型謂詞如何與原始類型一起工作。假設(shè)我們有一個(gè)接受類型為 any 的變量的函數(shù),我們想檢查它是否是字符串。我們可以這樣定義一個(gè)類型謂詞函數(shù):通過使用 JavaScript 中的 typeof 操作符來(lái)判斷變量是否為字符串。如果變量是字符串,函數(shù)將返回 true;否則返回 false。
現(xiàn)在,我們?cè)跅l件語(yǔ)句中使用這個(gè)類型謂詞函數(shù),通過 isString 函數(shù)檢查變量是否是字符串,并打印我們選擇的結(jié)果。
let variable: any = 'hello';
if (isString(variable)) {
console.log("給定的變量是字符串類型");
}
function isString(variable: any): variable is string {
return typeof variable === 'string';
}輸出:

2. 帶自定義類型的類型謂詞
下面通過另一個(gè)例子來(lái)理解類型謂詞如何與自定義類型配合使用。假設(shè)我們有一個(gè)表示“Person”對(duì)象的接口。接著,我們定義一個(gè)類型謂詞函數(shù),用于檢查某個(gè)變量是否為“Person”類型。函數(shù)通過使用 in 操作符檢查變量是否包含 name、age 和 address 屬性。如果變量是“Person”類型,函數(shù)返回 true;否則返回 false。然后我們可以在條件語(yǔ)句中使用這個(gè)類型謂詞函數(shù)。如果函數(shù)返回 true,我們就可以安全地訪問“address”對(duì)象中的 city 屬性,因?yàn)榇藭r(shí)我們已經(jīng)知道變量的類型是“Person”。
interface Person {
name: string;
age: number;
address: {
street: string;
city: string;
zip: number;
};
}
// 定義類型謂詞函數(shù),判斷變量是否為 Person 類型
function isPerson(variable: any): variable is Person {
return (
typeof variable === "object" && // 判斷變量是對(duì)象
variable !== null && // 且不為 null
"name" in variable && // 并且擁有 name 屬性
"age" in variable && // 擁有 age 屬性
"address" in variable // 擁有 address 屬性
);
}
let variable: any = {
name: "John",
age: 30,
address: {
street: "皂君廟甲10號(hào)",
city: "北京",
zip: 10001
},
};
// 如果變量是 Person 類型,則安全訪問 address.city 屬性
if (isPerson(variable)) {
console.log(variable.address.city);
}輸出:

到此這篇關(guān)于TypeScript 類型縮小的幾種實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)TypeScript 類型縮小內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript操作向表格中動(dòng)態(tài)加載數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了javascript操作向表格中動(dòng)態(tài)加載數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
多瀏覽器兼容的動(dòng)態(tài)加載 JavaScript 與 CSS
Omar AL Zabir這位MVP總是喜歡搞些稀奇古怪同時(shí)又很實(shí)用的小東西,并且還十分值得參考。最近他就做了一個(gè)叫做ensure的小工具用于動(dòng)態(tài)加載JavaScript、CSS與HTML,而且IE、Firefox、Opera、Safari都支持了,那么我們就來(lái)看看ensure是如何做到動(dòng)態(tài)加載JavaScript與CSS的。2008-09-09
javascript循環(huán)鏈表之約瑟夫環(huán)的實(shí)現(xiàn)方法
這是一道比較經(jīng)典的循環(huán)鏈表問題,在華為上機(jī)筆試中也出現(xiàn)過。 約瑟夫環(huán)是一個(gè)數(shù)學(xué)的應(yīng)用問題,下面這篇文章主要就給大家介紹了javascript循環(huán)鏈表之約瑟夫環(huán)的實(shí)現(xiàn)方法,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-01-01
一行JavaScript代碼如何實(shí)現(xiàn)瀑布流布局
這篇文章主要給大家介紹了如何通過一行JavaScript代碼實(shí)現(xiàn)瀑布流布局的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12

