最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

TypeScript 類型守衛(wèi)的實現(xiàn)示例

 更新時間:2026年05月13日 09:06:20   作者:燭銜溟  
本文主要介紹了TypeScript 類型守衛(wèi)的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、什么是類型守衛(wèi)

類型守衛(wèi)是 TypeScript 中用于在運行時檢查類型,并在編譯時相應(yīng)收窄類型范圍的技術(shù)。通過類型守衛(wèi),聯(lián)合類型可以被細化為更具體的類型,從而安全地訪問特有屬性或方法。

function example(value: string | number) {
    // value 類型為 string | number
    if (typeof value === "string") {
        // 這里 value 被收窄為 string
        console.log(value.toUpperCase());
    } else {
        // 這里 value 被收窄為 number
        console.log(value.toFixed(2));
    }
}

typeof value === "string" 就是一個類型守衛(wèi)。

二、typeof 類型守衛(wèi)

2.1 基本用法

typeof 運算符判斷 JavaScript 基本類型,支持:"string"、"number""boolean"、"symbol"、"bigint""undefined"、"object""function"。

function process(input: string | number | boolean) {
    if (typeof input === "string") {
        console.log(input.length);   // string
    } else if (typeof input === "number") {
        console.log(input.toFixed(2)); // number
    } else {
        console.log(input);          // boolean
    }
}

2.2 識別 null 和數(shù)組的問題

typeof null 返回 "object",typeof [] 也返回 "object",無法區(qū)分。

function handle(value: string | null) {
    if (typeof value === "object") {  // null 也會進入這里
        // 這里 value 類型為 null
    }
}

對于數(shù)組,需要額外判斷:

if (Array.isArray(value)) {
    // value 收窄為數(shù)組
}

2.3 多個類型守衛(wèi)組合

可以使用 ||&& 組合條件,TypeScript 能正確收窄。

function fn(value: string | number[] | null) {
    if (typeof value === "object" && value !== null) {
        // value 收窄為 number[]
    }
}

三、instanceof 類型守衛(wèi)

instanceof 用于判斷對象是否是某個類的實例,適用于類繼承場景。

class Dog {
    bark() { console.log("woof"); }
}

class Cat {
    meow() { console.log("meow"); }
}

function makeSound(animal: Dog | Cat) {
    if (animal instanceof Dog) {
        animal.bark();  // 收窄為 Dog
    } else {
        animal.meow();  // 收窄為 Cat
    }
}

instanceof 也能識別內(nèi)置類型,如 Date、RegExpError 等。

function formatDate(value: string | Date) {
    if (value instanceof Date) {
        return value.toLocaleDateString();
    }
    return value;
}

注意:instanceof 對字面量類型無效,對接口也無效(接口在運行時不存在)。

四、in 運算符類型守衛(wèi)

in 用于檢查對象是否包含某個屬性,常用于區(qū)分具有不同屬性集的類型。

interface Circle {
    kind: "circle";
    radius: number;
}

interface Square {
    kind: "square";
    sideLength: number;
}

function area(shape: Circle | Square) {
    if ("radius" in shape) {
        return Math.PI * shape.radius ** 2;  // shape 收窄為 Circle
    } else {
        return shape.sideLength ** 2;        // shape 收窄為 Square
    }
}

in 守衛(wèi)比直接判斷 kind 字段更通用,但需要確保屬性名在類型中唯一。

五、自定義類型守衛(wèi)(is)

5.1 為什么需要自定義守衛(wèi)

當(dāng)內(nèi)置守衛(wèi)無法滿足復(fù)雜判斷時(如判斷對象是否為特定形狀、判斷字符串是否為有效郵箱等),可以編寫返回類型謂詞 parameterName is Type 的函數(shù)。

5.2 基本語法

function isString(value: unknown): value is string {
    return typeof value === "string";
}

function process(value: unknown) {
    if (isString(value)) {
        console.log(value.length);  // value 收窄為 string
    }
}

返回類型 value is string 就是類型謂詞。函數(shù)體返回 boolean,TypeScript 會在 if 條件中根據(jù)返回值收窄類型。

5.3 復(fù)雜對象守衛(wèi)

interface User {
    name: string;
    age: number;
}

function isUser(obj: any): obj is User {
    return obj && typeof obj.name === "string" && typeof obj.age === "number";
}

function greet(data: unknown) {
    if (isUser(data)) {
        console.log(`Hello, ${data.name}`);  // data 是 User
    }
}

5.4 泛型守衛(wèi)

類型守衛(wèi)也可以使用泛型。

function isArrayOf<T>(value: unknown, check: (item: unknown) => item is T): value is T[] {
    return Array.isArray(value) && value.every(check);
}

const isNumber = (x: unknown): x is number => typeof x === "number";

const data: unknown = [1, 2, 3];
if (isArrayOf(data, isNumber)) {
    // data 類型為 number[]
    console.log(data.reduce((a,b)=>a+b,0));
}

5.5 守衛(wèi)的局限

類型謂詞必須使用參數(shù)名,不能使用復(fù)雜的表達式。一個函數(shù)最多只能有一個類型謂詞。

// 錯誤:不能有兩個謂詞
function isXOrY(value: any): value is X | value is Y { ... }

如果需要判斷多種類型,返回聯(lián)合類型的謂詞也是合法的(value is Type1 | Type2)。

六、斷言函數(shù)(asserts)簡介

6.1 基本概念

斷言函數(shù)是另一種類型守衛(wèi),當(dāng)條件不滿足時拋出錯誤,從而收窄后續(xù)代碼中的類型。

語法:asserts conditionasserts value is Type。

function assertIsString(value: unknown): asserts value is string {
    if (typeof value !== "string") {
        throw new Error("Not a string");
    }
}

function toUpper(value: unknown) {
    assertIsString(value);
    // 此處 value 類型被收窄為 string
    return value.toUpperCase();
}

6.2 與類型守衛(wèi)的區(qū)別

  • 類型守衛(wèi)返回 boolean,用于 if 分支收窄。
  • 斷言函數(shù)不返回值(或返回 void),如果條件失敗則拋出異常,后續(xù)代碼假設(shè)斷言成立。
// 類型守衛(wèi)
if (isString(value)) {
    // value 是 string
}

// 斷言函數(shù)
assertIsString(value);
// value 是 string(無需包裹在 if 里)

6.3 簡單斷言

也可以直接斷言某個條件為真,不限于類型收窄。

function assert(condition: any, msg?: string): asserts condition {
    if (!condition) throw new Error(msg ?? "Assertion failed");
}

function process(value: string | null) {
    assert(value !== null);
    // 此處 value 被收窄為 string(非 null)
}

七、常見錯誤與注意事項

7.1 typeof 對 null 的判斷誤區(qū)

if (typeof obj === "object") {
    // obj 可能是 null 或 {},需要額外排除 null
    if (obj !== null) {
        // ...
    }
}

7.2 instanceof 對原始類型無效

let str = "hello";
console.log(str instanceof String);  // false(str 是字符串字面量,不是 String 對象)

使用 typeof 判斷原始類型更合適。

7.3 自定義守衛(wèi)需要嚴格實現(xiàn)

類型謂詞不會自動檢查函數(shù)體的邏輯是否正確,需要開發(fā)者保證返回 true 時參數(shù)確實符合聲明的類型。

function isFish(pet: any): pet is Fish {
    // 錯誤實現(xiàn):即使 pet 不是 Fish 也返回 true
    return true;  // 危險!TypeScript 會信任這個斷言
}

7.4 斷言函數(shù)不能用于箭頭函數(shù)?

斷言函數(shù)可以用箭頭函數(shù),但返回類型必須寫 asserts condition。

const assertString = (value: unknown): asserts value is string => {
    if (typeof value !== "string") throw new Error();
};

7.5 守衛(wèi)順序與性能

多個守衛(wèi)可能重復(fù)檢查,可以按開銷從小到大排序。

八、綜合示例

// 定義幾種數(shù)據(jù)類型
interface Car {
    wheels: number;
    drive(): void;
}

interface Boat {
    sails: number;
    sail(): void;
}

interface Plane {
    wings: number;
    fly(): void;
}

type Vehicle = Car | Boat | Plane;

// 自定義類型守衛(wèi)
function isCar(vehicle: Vehicle): vehicle is Car {
    return "drive" in vehicle;
}

function isBoat(vehicle: Vehicle): vehicle is Boat {
    return "sail" in vehicle;
}

function isPlane(vehicle: Vehicle): vehicle is Plane {
    return "fly" in vehicle;
}

// 使用守衛(wèi)
function operate(vehicle: Vehicle) {
    if (isCar(vehicle)) {
        vehicle.drive();
    } else if (isBoat(vehicle)) {
        vehicle.sail();
    } else if (isPlane(vehicle)) {
        vehicle.fly();
    } else {
        const _exhaustive: never = vehicle;
    }
}

// 斷言函數(shù)示例:確保值非空且為數(shù)字
function assertNumber(value: unknown): asserts value is number {
    if (typeof value !== "number") {
        throw new TypeError("Expected a number");
    }
}

function increment(value: unknown) {
    assertNumber(value);
    return value + 1;  // value 已收窄為 number
}

// 復(fù)雜對象守衛(wèi)
interface ApiResponse {
    status: number;
    data?: unknown;
}

function isSuccessResponse(resp: ApiResponse): resp is ApiResponse & { status: 200; data: object } {
    return resp.status === 200 && resp.data !== null && typeof resp.data === "object";
}

const response: ApiResponse = { status: 200, data: { id: 1 } };
if (isSuccessResponse(response)) {
    console.log(response.data.id);  // 安全訪問
}

九、小結(jié)

守衛(wèi)類型語法示例適用場景
typeoftypeof x === "string"基本類型判斷
instanceofx instanceof Date類實例判斷
in"prop" in obj對象屬性存在判斷
自定義 isfunction isT(x: any): x is T { ... }復(fù)雜類型判斷、接口形狀判斷
斷言 assertsfunction assertIsT(x: any): asserts x is T失敗拋異常,后續(xù)代碼自動收窄

到此這篇關(guān)于TypeScript 類型守衛(wèi)的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)TypeScript 類型守衛(wèi)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

阿瓦提县| 舞钢市| 萨迦县| 芜湖市| 常山县| 绥棱县| 通辽市| 隆德县| 景洪市| 霍山县| 龙陵县| 温州市| 乌拉特后旗| 应城市| 康保县| 启东市| 广州市| 眉山市| 甘谷县| 锦州市| 城口县| 永善县| 永安市| 渑池县| 东安县| 甘肃省| 宣威市| 静乐县| 灵石县| 杭锦旗| 安国市| 肃南| 柏乡县| 康平县| 林口县| 长乐市| 常山县| 德惠市| 页游| 明光市| 东台市|