詳解Typescript?嚴(yán)格模式有多嚴(yán)格
正文
TypeScript 是微軟于 2012 年推出的一門(mén)語(yǔ)言,它是 JavaScript 的超集,具有更強(qiáng)的可選類(lèi)型系統(tǒng)。TypeScript 和 JavaScript 一樣是有嚴(yán)格模式的,今天就來(lái)看看 TypeScript 中的嚴(yán)格模式如何開(kāi)啟,以及它到底有多嚴(yán)格!
TypeScript 的配置項(xiàng)都寫(xiě)在項(xiàng)目根目錄名為 tsconfig.json 的配置文件中,可以通過(guò)以下方式來(lái)開(kāi)啟嚴(yán)格模式:
{
...
"compilerOptions": {
"strict": true,
...
},
...
}
TypeScript 編譯器有超過(guò) 90 個(gè)不同的配置項(xiàng)。其中 7 個(gè)是關(guān)于嚴(yán)格模式的:
- noImplicitAny
- noImplicitThis
- alwaysStrict
- strictBindCallApply
- strictNullChecks
- strictPropertyInitialization
- strictFunctionTypes
當(dāng)在 tsconfig.json 中開(kāi)啟嚴(yán)格模式之后,就相當(dāng)于開(kāi)啟了這些配置:
{
...
"compilerOptions": {
"noImplicitAny": true,
"noImplicitThis": true,
"alwaysStrict": true,
"strictBindCallApply": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
...
}
...
}
下面就來(lái)分別看一下這些選項(xiàng)都有什么含義。
noImplicitAny
此規(guī)則不允許變量或函數(shù)參數(shù)具有隱式 any 類(lèi)型。來(lái)看下面的例子:
const add10 = number => number + 10;
當(dāng)啟用了嚴(yán)格模式時(shí),函數(shù)參數(shù) number 就報(bào)錯(cuò)了:
參數(shù)“number”隱式具有“any”類(lèi)型。ts(7006)
要想修復(fù)這個(gè)報(bào)錯(cuò),只需給參數(shù)或變量顯式指定類(lèi)型:
const add10 = (number: number) => number + 10;
因此 noImplicitAny 規(guī)則可以確保代碼更具可讀性。否則,add10 函數(shù)的調(diào)用者需要推斷參數(shù)是一個(gè)數(shù)字,那使用 TypeScript 還有什么意義呢?
noImplicitThis
此規(guī)則不允許 this 隱式定義上下文。來(lái)看下面的例子:
class Person {
weight: number;
height: number;
constructor(weight: number, height: number) {
this.weight = weight;
this.height = height;
}
getBodyMassIndex() {
return function () {
return this.weight / (this.height * this.height);
};
}
}
當(dāng)啟用了嚴(yán)格模式時(shí),getBodyMassIndex 中的 this 就報(bào)錯(cuò)了:
"this" 隱式具有類(lèi)型 "any",因?yàn)樗鼪](méi)有類(lèi)型注釋。ts(2683)
解決這個(gè)問(wèn)題的方法就是使用箭頭函數(shù),因?yàn)榧^函數(shù)使用其父級(jí)的執(zhí)行上下文:
class Person {
weight: number;
height: number;
constructor(weight: number, height: number) {
this.weight = weight;
this.height = height;
}
getBodyMassIndex() {
return () => {
return this.weight / (this.height * this.height);
};
}
}
alwaysStrict
此規(guī)則指定始終以嚴(yán)格模式檢查每個(gè)模塊,并且在編譯之后的 JavaScript 文件中加入"use strict",用來(lái)告訴瀏覽器該 JavaScript 為嚴(yán)格模式。
ECMAScript 嚴(yán)格模式是在 ES5 中引入的,它只是向編譯器提示代碼應(yīng)該以嚴(yán)格模式執(zhí)行,使用嚴(yán)格模式可以使代碼更以更安全、高效的方式運(yùn)行。
strictBindCallApply
此規(guī)則可以確保使用具有正確參數(shù)的 call()、bind() 和 apply() 函數(shù)。來(lái)看下面的例子:
const logNumber = (x: number) => {
console.log(`number:${x}`)
}
logNumber.call(undefined, "10"); //
當(dāng)啟用了嚴(yán)格模式時(shí),getBodyMassIndex 中的 this 就報(bào)錯(cuò)了:
類(lèi)型“string”的參數(shù)不能賦給類(lèi)型“number”的參數(shù)。ts(2345)
當(dāng)遇到這種報(bào)錯(cuò)時(shí),只需檢查函數(shù)調(diào)用的參數(shù),并使用正常的方式調(diào)用:
logNumber.call(undefined, 10); // number:10
strictNullChecks
此規(guī)則使得 null和 undefined 值不能賦值給非這兩種類(lèi)型的值,別的類(lèi)型的值也不能賦給它們。除了 any 類(lèi)型,還有個(gè)例外就是 undefined 可以賦值給 void 類(lèi)型。這個(gè)選項(xiàng)可以幫助 Uncaught TypeError 錯(cuò)誤。來(lái)看下面的例子:
interface Book {
name: string;
author: string;
}
const books: Book[] = [ {name: 'Test1', author: 'Max'} ];
const getBookByAuthor = (author: string) => books.find((book) => book.author = author);
const book = getBookByAuthor("John");
console.log(book.name);
當(dāng)啟用了嚴(yán)格模式時(shí),打印 book.name 時(shí)就報(bào)錯(cuò)了:
對(duì)象可能為“未定義”。ts(2532)
如果未開(kāi)啟嚴(yán)格模式,即使 book.name 可能未定義,此代碼也會(huì)編譯。想要修復(fù)這個(gè)問(wèn)題,就需要為要編譯的代碼添加 null 檢查:
interface Book {
name: string;
author: string;
}
const books: Book[] = [ {name: 'Test1', author: 'Max'} ];
const getBookByAuthor = (author: string) => books.find((book) => book.author = author);
const book = getBookByAuthor("John");
if (book) {
console.log(book.name);
} else {
console.log('Book not found');
}
函數(shù)中也是一樣的,來(lái)看下面的例子:
interface Book {
name: string;
author: string;
}
const books: Book[] = [ {name: 'Test1', author: 'Max'} ];
const getBookByAuthor = (author: string) => books.find((book) => book.author = author);
const book = getBookByAuthor("John");
const logBookName = (book: Book) => {
console.log(book.name);
}
logBookName(book);
如果啟用了嚴(yán)格模式時(shí),調(diào)用 logBookName(book); 時(shí)就會(huì)報(bào)錯(cuò):
類(lèi)型“Book | undefined”的參數(shù)不能賦給類(lèi)型“Book”的參數(shù)。
不能將類(lèi)型“undefined”分配給類(lèi)型“Book”。ts(2345)
這里提供兩種解決方案:
- A:將
logBookName函數(shù)參數(shù)類(lèi)型設(shè)置為Book | undefined - B:
null檢查條件調(diào)用
// A
const logBookName = (book: Book | undefined) => {
if (book) {
console.log(book.name);
}
else {
console.log('not book');
}
}
// B
if (book) {
logBookName(book);
}
使用該規(guī)則時(shí),可以強(qiáng)制開(kāi)發(fā)人員編寫(xiě)具有更好類(lèi)型描述的代碼。
strictPropertyInitialization
此規(guī)則將強(qiáng)制在構(gòu)造函數(shù)中初始化所有屬性值。來(lái)看下面的例子:
class User {
name: string;
age: number;
occupation: string | undefined;
constructor(name: string) {
this.name = name;
}
}
在上面的代碼塊中有一個(gè) User 類(lèi),constructor() 方法是初始化其實(shí)例屬性的地方。當(dāng)實(shí)例化一個(gè)類(lèi)對(duì)象時(shí),JavaScript 會(huì)自動(dòng)調(diào)用 constructor() 方法。Typescript 要求要么初始化定義的屬性,要么指定一個(gè) undefined 類(lèi)型。因此,當(dāng)編譯上面的代碼時(shí),將會(huì)提示以下錯(cuò)誤:
屬性“age”沒(méi)有初始化表達(dá)式,且未在構(gòu)造函數(shù)中明確賦值。ts(2564)
對(duì)于上面的代碼,可以這樣改:
// A:指定 undefined 類(lèi)型
class User {
name: string;
age: number | undefined;
occupation: string | undefined;
constructor(name: string) {
this.name = name;
}
}
// B:初始化定義的屬性
class User {
name: string;
age: number;
occupation: string | undefined;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
strictFunctionTypes
此規(guī)則會(huì)更徹底地檢查函數(shù)參數(shù)。Typescript 參數(shù)默認(rèn)是雙向協(xié)變的,這意味著它們既可以是協(xié)變的,也可以是逆變的。方差是一種深入了解子類(lèi)型關(guān)系的方法。當(dāng)參數(shù)是協(xié)方差時(shí),我們可以將特定類(lèi)型分配給更廣泛的類(lèi)型(例如將子類(lèi)型分配給超類(lèi)型)。逆變是相反的:可以將更廣泛的類(lèi)型分配給特定類(lèi)型(例如將超類(lèi)型分配給子類(lèi)型)。
// 非嚴(yán)格模式
interface Animal {
name: string;
}
interface Dog extends Animal {
breeds: Array<string>;
}
let getDogName = (dog: Dog) => dog.name;
let getAnimalName = (animal: Animal) => animal.name;
getDogName = getAnimalName; // Ok
getAnimalName = getDogName; // Ok
上面的代碼運(yùn)行時(shí)并沒(méi)有提示錯(cuò)誤,默認(rèn)情況下參數(shù)是雙向協(xié)變比較的。超類(lèi)型 getAnimalName 和子類(lèi)型 getDogName 的方法可以相互分配。當(dāng)開(kāi)啟嚴(yán)格模式之后,則 TypeScript 的參數(shù)進(jìn)行逆變比較。
// 嚴(yán)格模式
interface Animal {
name: string;
}
interface Dog extends Animal {
breeds: Array<string>;
}
let getDogName = (dog: Dog) => dog.name;
let getAnimalName = (animal: Animal) => animal.name;
getDogName = getAnimalName; // Ok
getAnimalName = getDogName; // Error
當(dāng)開(kāi)啟嚴(yán)格模式時(shí),最后一行將報(bào)以下錯(cuò)誤:
不能將類(lèi)型“(dog: Dog) => string”分配給類(lèi)型“(animal: Animal) => string”。
參數(shù)“dog”和“animal” 的類(lèi)型不兼容。
類(lèi)型 "Animal" 中缺少屬性 "breeds",但類(lèi)型 "Dog" 中需要該屬性。ts(2322)
這里,getAnimalName 是比 getDogName 更廣泛的函數(shù)。因此,在這種情況下,無(wú)法將超類(lèi)型分配給子類(lèi)型。但是,可以將子類(lèi)型分配給超類(lèi)型。大多數(shù)時(shí)候,函數(shù)參數(shù)應(yīng)該是逆變的,而不是雙向協(xié)變的。如果開(kāi)啟嚴(yán)格模式,Typescript 將不會(huì)將函數(shù)參數(shù)視為雙向協(xié)變。
以上就是詳解Typescript 嚴(yán)格模式有多嚴(yán)格的詳細(xì)內(nèi)容,更多關(guān)于Typescript 嚴(yán)格模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 數(shù)據(jù)結(jié)構(gòu)TypeScript之鏈表實(shí)現(xiàn)詳解
- 數(shù)據(jù)結(jié)構(gòu)Typescript之哈希表實(shí)現(xiàn)詳解
- 數(shù)據(jù)結(jié)構(gòu)TypeScript之鄰接表實(shí)現(xiàn)示例詳解
- 簡(jiǎn)單三行代碼函數(shù)實(shí)現(xiàn)幾十行Typescript類(lèi)型推導(dǎo)
- 項(xiàng)目中使用TypeScript的TodoList實(shí)例詳解
- TypeScript中的交叉類(lèi)型和聯(lián)合類(lèi)型示例講解
- 數(shù)據(jù)結(jié)構(gòu)TypeScript之二叉查找樹(shù)實(shí)現(xiàn)詳解
相關(guān)文章
typescript封裝消息提示框插件ew-message使用實(shí)戰(zhàn)
這篇文章主要為大家介紹了typescript封裝消息提示框插件ew-message使用實(shí)戰(zhàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
Typescript使用裝飾器實(shí)現(xiàn)接口字段映射與Mock實(shí)例
這篇文章主要為大家介紹了Typescript使用裝飾器實(shí)現(xiàn)接口字段映射與Mock實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
TypeScript 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)哈希表 HashTable教程
這篇文章主要為大家介紹了TypeScript 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)哈希表 HashTable教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
less簡(jiǎn)單入門(mén)(CSS 預(yù)處理語(yǔ)言)
Less 是一門(mén) CSS 預(yù)處理語(yǔ)言,它擴(kuò)充了 CSS 語(yǔ)言,增加了諸如變量、混合(mixin)、函數(shù)等功能,讓 CSS 更易維護(hù)、方便制作主題、擴(kuò)充2017-03-03
rollup?cli開(kāi)發(fā)全面系統(tǒng)性rollup源碼分析
這篇文章主要為大家介紹了rollup?cli開(kāi)發(fā)全網(wǎng)系統(tǒng)性rollup源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01

