Typescript中的as、問號與感嘆號


1、as關鍵字表示斷言
在Typescript中,表示斷言有兩種方式。一種是擴號表示法:

let someValue: any = "this is a string";
let strLength: number = (someValue).length;
1
2
另一種使用as關鍵字:

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
1
2
2、問號(?)用於屬性定義
問號表示可選的屬性,一般用於屬性定義,如,用於接口時:

interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig) {
if (config.color) {
console.log(config);
}
}
1
2
3
4
5
6
7
8
9
可選屬性的含義是:使用這個屬性時,要么這個屬性名不存在,要么必須符合屬性的類型定義

比如上述createSquare函數編譯時會報error錯誤:

error TS2551: Property 'clor' does not exist on type 'SquareConfig'.
1
如果修改createSquare,將config.color的值改為undefined,會怎樣?

interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig) {
config.color = undefined;
if (config.color) {
console.log(config);
}
}
1
2
3
4
5
6
7
8
9
10
這時並沒有編譯報錯!明明config.color定義的是string類型呀?

即便是添加–strictNullChecks進行編譯,也不會報錯。可見,可選屬性所定義的類型,並沒有被typescript嚴格地對待,默認並不檢查undefined。需要注意的是,將上述undefined改成null時,普通編譯也不報錯,–strictNullChecks編譯會報如下錯誤:

error TS2322: Type 'null' is not assignable to type 'string | undefined'
1
從這句報錯中,我們可以得出這樣的結論:可選屬性等價於一個union類型,union了undefined;不加–strictNullChecks編譯時,null可以賦值給undfined類型。也就是說,SquareConfig的定義與下面的代碼等價:

interface SquareConfig {
color: string|undefined;
width: number|undefined;
}
1
2
3
4
下面比較一下可選屬性與正常屬性。再次修改createSquare,將color屬性修改為正常屬性。

interface SquareConfig {
color: string;
width?: number;
}
function createSquare(config: SquareConfig) {
config.color = undefined;
if (config.color) {
console.log(config);
}
}
1
2
3
4
5
6
7
8
9
10
以–strictNullChecks編譯,報錯了:

error TS2322: Type ‘undefined’ is not assignable to type ‘string’

這個比較也驗證了上述的結論。

問號(?)用於屬性讀取

問號用於屬性讀取,主要有兩個場景:一是讀取數組元素(如下面的node[i]),二是讀取不確定的類型如any,union,可選類型(如node[i].data)等。如下例,保存為index.ts:

interface VNodeData {
class?: string;
}
interface VNode {
sel?: string;
data?: VNodeData;
}
function test(node: VNode[]) {
let i = 0;
var b = node[i].data.class;
if(b !== undefined) {
console.log(1);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
用tsc --strictNullChecks index.ts,報錯:.

error TS2532: Object is possibly 'undefined'
1
下面將一一展示這一行代碼var b = node[i].data.class;修改改后的效果。

1、修改為var b = node[i]?.data.class;,然后編譯。報錯:

Object is possibly 'undefined'
1
2、修改為var b = node[i]?.data?.class;,然后編譯。編譯通過,查看編譯后的對應代碼為:

function test(node) {
var _a, _b;
var i = 0;
var b = (_b = (_a = node[i]) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b["class"];
// var b = node[i].data.class;//報錯
if (b !== undefined) {
console.log(1);
}
}
1
2
3
4
5
6
7
8
9
var b = node[i]?表示,如果node[i]的值為null或者undefined,則b等於undefined,否則b=node[i]。

3、修改為var b = (node[i] as VNode).data?.class;,然后編譯。編譯通過,查看編譯后的對應代碼為:

function test(node) {
var _a;
var i = 0;
var b = (_a = node[i].data) === null || _a === void 0 ? void 0 : _a["class"];
// var b = node[i]?.data?.class;
// var b = node[i].data.class;//報錯
if (b !== undefined) {
console.log(1);
}
}
1
2
3
4
5
6
7
8
9
10
此時,使用node[i]時,Typescript編譯器將不再對其判斷是否為null和undefined。即:var b = node[i] as VNode直接會被編成var b = node[i]。

4、修改為var b = node[i]!.data?.class,然后編譯。編譯通過,查看編譯后的對應代碼為:

function test(node) {
var _a;
var i = 0;
var b = (_a = node[i].data) === null || _a === void 0 ? void 0 : _a["class"];
// var b = (node[i] as VNode).data?.class
// var b = node[i]?.data?.class;
// var b = node[i].data.class;//報錯
if (b !== undefined) {
console.log(1);
}
}
1
2
3
4
5
6
7
8
9
10
11
可見,3和4的編譯后代碼完全一樣,!的作用此時與as是等價的。然而,!只是用來判斷null和undefined;as則可用於變更(縮小或者放大都可以)類型檢測范圍,僅當as后面跟的類型是一個非空類型時,兩者才等價。如下例中,不能將as用法改為!。

interface Cat {
action: string;
}
interface Dog {
action: string;
}
type Animal = Cat | Dog;
let action:Animal = {} as Cat;
1
2
3
4
5
6
7
8
結論
1、as和!用於屬性的讀取,都可以縮小類型檢查范圍,都做判空用途時是等價的。只是!具體用於告知編譯器此值不可能為空值(null和undefined),而as不限於此。

2、?可用於屬性的定義和讀取,讀取時告訴編譯器此值可能為空值(null和undefined),需要做判斷。
————————————————
版權聲明:本文為CSDN博主「longzhoufeng」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/longzhoufeng/article/details/106240989


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM