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

TypeScript 類型斷言與非空斷言的實現(xiàn)

 更新時間:2026年05月12日 09:18:15   作者:燭銜溟  
本文深入解析 TypeScript 中的類型斷言(as/<>)與非空斷言(!)的核心用法與風險,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

一、類型斷言(Type Assertion)

1.1 什么是類型斷言

類型斷言告訴 TypeScript 編譯器:“我知道這個值的實際類型,請按我指定的類型來理解。”它只在編譯時生效,不會改變運行時的值。

使用場景:當 TypeScript 推斷的類型不夠精確,而開發(fā)者掌握更多信息時。

1.2 兩種語法

方式一:as 關鍵字(推薦)

let someValue: unknown = "this is a string";
let strLength: number = (someValue as string).length;

方式二:尖括號 <>(在 JSX 中可能沖突)

let someValue: unknown = "this is a string";
let strLength: number = (<string>someValue).length;

在 React 的 TSX 文件中,尖括號語法會被解析為 JSX 標簽,因此統(tǒng)一使用 as 更穩(wěn)妥。

1.3 斷言的限制

類型斷言并非“強制轉換”。它只能用于兩個類型之間存在包含關系時(即一個是另一個的子類型,或兩者有重疊)。

let x = "hello" as number;      // ? 類型 "string" 不能斷言為 "number"
let y = "hello" as any as number; // OK(雙重斷言,先轉 any 再轉 number,不推薦)

雙重斷言(as any as T)雖然能繞過檢查,但通常意味著設計有問題,應盡量避免。

1.4 類型斷言 vs 類型轉換

  • 類型斷言:只影響 TypeScript 編譯時的類型檢查,不改變運行時的值。沒有額外的運行時行為。
  • 類型轉換:JavaScript 運行時真正轉換值的類型(如 Number(value)、String(value))。
let value: unknown = "123";
let asserted = value as number;      // 編譯通過,運行時 asserted 仍然是字符串 "123"
let converted = Number(value);       // 運行時變?yōu)閿?shù)字 123

1.5 DOM 操作中的典型應用

TypeScript 無法識別 document.getElementById 返回的具體元素類型,默認返回 HTMLElement | null。使用類型斷言可以指定更精確的類型。

const canvas = document.getElementById("myCanvas") as HTMLCanvasElement;
const ctx = canvas.getContext("2d");  // 現(xiàn)在 canvas 被識別為 HTMLCanvasElement

const input = document.querySelector("input") as HTMLInputElement;
console.log(input.value);             // 正確識別 value 屬性

常見 DOM 元素類型:HTMLDivElement、HTMLButtonElement、HTMLAnchorElement、HTMLImageElement 等。

1.6 斷言與字面量收窄

as const 是特殊的斷言,用于將整個表達式推斷為只讀字面量類型。

let colors = ["red", "green"] as const;  // 類型為 readonly ["red", "green"]
let color = colors[0];                    // 類型為 "red"

二、非空斷言(Non-null Assertion)

2.1 語法與作用

非空斷言使用后綴 !,告訴 TypeScript:“這個值一定不是 nullundefined,請放心使用。”

let maybeValue: string | null = "hello";
let definitelyValue: string = maybeValue!;  // 斷言非空

常用于從 Map.getdocument.getElementById、數(shù)組.find 等可能返回空值的方法中獲取值。

2.2 使用場景

場景一:DOM 元素一定存在

const app = document.getElementById("app")!;
app.innerHTML = "Mounted";

場景二:Array.find 結果一定存在

const users = [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
const user = users.find(u => u.id === 1)!;
console.log(user.name);

場景三:取消可選鏈中的可選性

interface User {
    address?: {
        city?: string;
    };
}

const user: User = { address: { city: "Beijing" } };
const city = user.address!.city;  // 斷言 address 存在

2.3 風險與注意事項

非空斷言不生成任何運行時檢查。如果斷言錯誤(值真的是 nullundefined),運行時就會拋出 Cannot read property of undefinedTypeError。

let value: string | null = null;
let len = value!.length;  // 編譯通過,運行時 TypeError: Cannot read property 'length' of null

更安全的替代方案

  • 使用條件判斷:if (value !== null) { ... }
  • 使用可選鏈:value?.length
  • 使用空值合并:value ?? defaultValue

2.4 與可選鏈的對比

方式編譯時檢查運行時安全適用場景
obj?.prop無斷言安全返回 undefined不確定是否有值
obj!.prop斷言非空不安全,可能報錯開發(fā)者 100% 確定有值
if (obj) { obj.prop }類型收窄安全需要分支邏輯的場景

2.5 非空斷言與賦值

當變量聲明時沒有立即初始化,且 TypeScript 嚴格模式下要求確保賦值時,非空斷言可以暫時緩解。

let x!: number;   // 明確告訴編譯器:x 會在使用前被賦值
initialize();
console.log(x);   // 不會報錯

function initialize() {
    x = 42;
}

這種用法稱為明確賦值斷言(definite assignment assertion),適用于變量確實會在使用前被賦值,但 TS 無法分析到的場景(如外部初始化)。

三、斷言與類型守衛(wèi)的選擇

類型斷言是“強行告訴編譯器”,類型守衛(wèi)是“運行時檢查并收窄類型”。優(yōu)先使用類型守衛(wèi)。

// 不推薦:斷言
function process(value: string | number) {
    (value as string).toUpperCase();  // 如果 value 是數(shù)字,運行時錯誤
}

// 推薦:類型守衛(wèi)
function process(value: string | number) {
    if (typeof value === "string") {
        value.toUpperCase();
    } else {
        value.toFixed(2);
    }
}

斷言的合理使用場景:

  • DOM 元素一定存在(如掛載點)
  • 從強邏輯保證非空的數(shù)據(jù)源(如 find 前已檢查長度)
  • 與第三方庫交互時,類型定義不準確且無法修改

四、常見錯誤與注意事項

4.1 濫用斷言導致隱藏錯誤

function getUser(id: number): { name: string } | null {
    if (id === 1) return { name: "Alice" };
    return null;
}

const user = getUser(2)!;   // 斷言非空,但實際為 null
console.log(user.name);     // 運行時崩潰

4.2 斷言與as const混淆

as const 是只讀字面量斷言,不涉及非空。注意區(qū)分:

let arr = [1, 2, 3] as const;   // 變成只讀元組
let first = arr[0];              // 類型為 1,不是非空斷言

4.3 在 React 事件處理中誤用斷言

// 不推薦
const handleClick = (e: MouseEvent) => {
    const target = e.target as HTMLButtonElement;
    target.disabled = true;  // 如果 target 不是 button,運行時錯誤
}

// 推薦:使用類型守衛(wèi)
const handleClick = (e: MouseEvent) => {
    if (e.target instanceof HTMLButtonElement) {
        e.target.disabled = true;
    }
}

4.4 尖括號斷言在 TSX 中的語法沖突

.tsx 文件中,<div> 會被解析為 JSX 元素,因此不能使用 <string>value 語法,必須使用 as。

五、綜合示例

// 模擬一個可能返回 null 的 API
function fetchElement(id: string): HTMLElement | null {
    const el = document.getElementById(id);
    return el;  // 可能為 null
}

// 場景一:確信元素存在,使用非空斷言
const app = fetchElement("app")!;
app.innerHTML = "<h1>Hello</h1>";

// 場景二:更安全的方式 + 類型守衛(wèi)
const maybeApp = fetchElement("app");
if (maybeApp) {
    maybeApp.style.backgroundColor = "blue";
}

// 場景三:類型斷言用于 DOM 元素具體類型
const canvas = document.getElementById("myCanvas") as HTMLCanvasElement;
const ctx = canvas.getContext("2d");
if (ctx) {
    ctx.fillRect(0, 0, 100, 100);
}

// 場景四:as const 與類型斷言的區(qū)別
const sizes = ["small", "medium", "large"] as const;
type Size = typeof sizes[number];  // "small" | "medium" | "large"

function setSize(size: Size) {
    // ...
}

setSize("small");   // OK
// setSize("huge");   // ? 類型錯誤

// 場景五:明確賦值斷言
let userInput!: string;   // 之后一定會在某處賦值
document.getElementById("input")?.addEventListener("input", (e) => {
    userInput = (e.target as HTMLInputElement).value;
});

六、小結

概念語法示例說明
類型斷言 asvalue as string告訴編譯器值的類型,不改變運行時
尖括號斷言<string>value與 as 等效,TSX 中不能用
雙重斷言value as any as number強制轉換任何類型,不推薦
非空斷言 !value!斷言值非 null/undefined
明確賦值斷言let x!: number聲明變量會在使用前賦值
as const[1,2] as const推斷為只讀字面量類型,不同于非空斷言

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

相關文章

  • javascript中的異步調(diào)用機制

    javascript中的異步調(diào)用機制

    這篇文章主要介紹了javascript中的異步調(diào)用機制,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • 10大Js圖像處理庫

    10大Js圖像處理庫

    這篇文章主要介紹了10大Js圖像處理庫,對圖像處理感興趣的同學,可以參考下
    2021-04-04
  • 原生js無縫輪播插件使用詳解

    原生js無縫輪播插件使用詳解

    這篇文章主要為大家詳細介紹了原生js無縫輪播插件的使用方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • layui 設置table 行的高度方法

    layui 設置table 行的高度方法

    今天小編就為大家分享一篇layui 設置table 行的高度方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • 微信小程序?qū)崿F(xiàn)人臉識別對比

    微信小程序?qū)崿F(xiàn)人臉識別對比

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)人臉識別對比,此文主要通過小程序?qū)崿F(xiàn)對比人臉相似度,并返回相似度分值,可以基于分值判斷是否為同一人,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-10-10
  • js中設置元素class的三種方法小結

    js中設置元素class的三種方法小結

    列舉所有的方式,看看各瀏覽器的支持差異。方便用js動態(tài)設置元素css的代碼。需要的朋友可以參考下。
    2011-08-08
  • 一文萬字詳解three.js+vue3.js實現(xiàn)教程

    一文萬字詳解three.js+vue3.js實現(xiàn)教程

    Three.js是一款基于WebGL的JavaScript 3D庫,它封裝了WebGL API,為開發(fā)者提供了簡單易用的API來在Web瀏覽器中展示3D圖形,這篇文章主要介紹了three.js+vue3.js實現(xiàn)的相關資料,需要的朋友可以參考下
    2025-08-08
  • JS獲取當前時間的年月日時分秒及時間的格式化的方法

    JS獲取當前時間的年月日時分秒及時間的格式化的方法

    這篇文章主要介紹了js獲取當前時間的年月日時分秒及時間的格式化,本文通過實例代碼講解的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-12-12
  • Nginx上傳文件全部緩存解決方案

    Nginx上傳文件全部緩存解決方案

    Nginx默認會對上傳的文件先在本地進行緩存,再轉發(fā)到應用服務器。請問怎么禁止掉這個緩存,讓Nginx只轉發(fā)而不緩存文件?本文給大家詳細介紹Nginx上傳文件全部緩存解決方案,有需要的朋友來參考下
    2015-08-08
  • GoJs中導出圖片或者SVG實現(xiàn)示例詳解

    GoJs中導出圖片或者SVG實現(xiàn)示例詳解

    這篇文章主要為大家介紹了GoJs中導出圖片或者SVG實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05

最新評論

高青县| 南皮县| 清远市| 腾冲县| 中山市| 桓仁| 定兴县| 慈利县| 南投市| 汤阴县| 左贡县| 马尔康县| 曲松县| 陵川县| 论坛| 宁河县| 满城县| 海晏县| 沈丘县| 临漳县| 孝昌县| 大冶市| 宝应县| 彭阳县| 防城港市| 土默特左旗| 青岛市| 五家渠市| 临邑县| 宣化县| 治县。| 宝鸡市| 周口市| 渭南市| 建昌县| 浦城县| 镇远县| 卓尼县| 沁水县| 肇东市| 朝阳市|