參考
巧用ES系列4: TypeScript中的問號 ? 與感嘆號 ! 是什么意思?
一、什么是 ?(問號)操作符飞傀?
在TypeScript里面,有4個地方會出現(xiàn)問號操作符,他們分別是
1.三元運算符
// 當 isNumber(input) 為 True 時返回 ? : 之間的部分淫僻;
// isNumber(input) 為 False 時返回 : ; 之間的部分
const a = isNumber(input) ? input : String(input);
2.可選參數(shù)
// 這里的 ?表示這個參數(shù) field 是一個可選參數(shù)
function getUser(user: string, field?: string) {
}
3.成員
// 這里的壶唤?表示這個name屬性有可能不存在
class A {
name?: string
}
interface B {
name?: string
}
4.安全鏈式調用
// 這里 Error對象定義的stack是可選參數(shù)雳灵,如果這樣寫的話編譯器會提示
// 出錯 TS2532: Object is possibly 'undefined'.
return new Error().stack.split('\n');
// 我們可以添加?操作符,當stack屬性存在時闸盔,調用 stack.split悯辙。
// 若stack不存在,則返回空
return new Error().stack?.split('\n');
// 以上代碼等同以下代碼, 感謝 @dingyanhe 的監(jiān)督
const err = new Error();
return err.stack && err.stack.split('\n');
二迎吵、什么是6阕(感嘆號)操作符?
在TypeScript里面有3個地方會出現(xiàn)感嘆號操作符击费,他們分別是
1.一元運算符
// ! 就是將之后的結果取反拢蛋,比如:
// 當 isNumber(input) 為 True 時返回 False;
// isNumber(input) 為 False 時返回True
const a = !isNumber(input);
2.成員
// 因為接口B里面name被定義為可空的值蔫巩,但是實際情況是不為空的瓤狐,
// 那么我們就可以通過在class里面使用!批幌,重新強調了name這個不為空值
class A implemented B {
name!: string
}
interface B {
name?: string
}
這里可以參考ts 更嚴格的類屬性檢查
Typescript 2.7 引入了一個新的控制嚴格性的標記 –strictPropertyInitialization, 這個參數(shù)在 tsconfig.ts 中來配置
"strictNullChecks": true
"strictPropertyInitialization": true
作用
- 使用這個標記會確保類的每個實例屬性都會在構造函數(shù)里或使用屬性初始化器賦值础锐。
- 它會明確地進行從變量到類的實例屬性的賦值檢查
舉例
class C {
foo: number;
bar = "hello";
baz: boolean;
constructor() {
this.foo = 42;
}
}
上述代碼,首先編輯器會報錯: 屬性“baz”沒有初始化表達式荧缘,且未在構造函數(shù)中明確賦值皆警。ts(2564)
。
其次在編譯報錯:error TS2564: Property 'baz' has no initializer and is not definitely assigned in the constructor.
兩種都告訴開發(fā)者截粗,應該給 baz 顯示賦值信姓,但是某種情況下鸵隧,在初始化的時候我們并不想賦值,更期望是 undefined意推,而后再去賦值豆瘫,此時 !: 就派上用場了。
在上述代碼中 屬性 baz 冒號之前加上 ! ,這樣就不會報錯了
class C {
foo: number;
bar = "hello";
baz!: boolean;
constructor() {
this.foo = 42;
}
}
3.強制鏈式調用
// 這里 Error對象定義的stack是可選參數(shù)菊值,如果這樣寫的話編譯器會提示
// 出錯 TS2532: Object is possibly 'undefined'.
new Error().stack.split('\n');
// 我們確信這個字段100%出現(xiàn)外驱,那么就可以添加!腻窒,強調這個字段一定存在
new Error().stack!.split('\n');