欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

TS 中的類型推斷與放寬實(shí)例詳解

 更新時(shí)間:2022年10月08日 10:13:37   作者:左肩有你  
這篇文章主要為大家介紹了TS 中的類型推斷與放寬實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

簡(jiǎn)介

我們知道在編碼時(shí)即使不標(biāo)注變量類型,TypeScript 編譯器也能推斷出變量類型,那 TypeScript 編譯器是怎么進(jìn)行類型推斷,在類型推斷時(shí)又是如何判斷兼容性的呢?

此文,正好為你解開(kāi)這個(gè)疑惑的,掌握本文講解的類型推斷與類型放寬知識(shí)點(diǎn)后將對(duì) TypeScript 的類型系統(tǒng)有更深的認(rèn)識(shí)。

不妨先看看下面幾個(gè)問(wèn)題,如果你都能回答上,那么可以不用閱讀此文了。

  • 這里變量 x 和 y 分別為什么類型,為什么?
let x = 0;
const y = 0;
  • 這里函數(shù)返回值、變量 x 為什么類型,為什么?
function f() {
 return 0
}
let x = f();
  • 這里 list 為什么類型,為什么?
const list = ['hello', 0];
  • 這里 x、y、a、b 為什么類型,為什么?
const x = 0;
let y = x;
const a: 0 = 0;
let b = a;

類型推斷與放寬概念

我們知道 JS 中表達(dá)式都具有返回值,在 TypeScript 程序中表達(dá)式也一樣具有返回值的同時(shí)還具有一種類型(返回值的類型),且此類型來(lái)源分為:類型注解、類型推斷。

類型注解是通過(guò)編寫代碼手動(dòng)指定表達(dá)式返回值的類型,如下代碼:

let x: number = 0; // 通過(guò)類型注解指定變量 x 為 number 類型

類型推斷指的是 TypeScript 編譯器自動(dòng)推測(cè)表達(dá)式返回值的類型,是一種比較智能的類型推測(cè)方法,可以簡(jiǎn)化代碼,如下代碼:

let x = 0; // 這里 TypeScript 編譯器自動(dòng)推斷變量 x 為 number 類型

上面兩段代碼中字面量 Literal 的值明明是字面量類型 0,但是變量 x 卻變?yōu)榱?number 類型。值的類型和推斷的變量類型不一致,這就涉及到 TypeScript 的類型放寬了。

常規(guī)類型推斷

上述代碼定義了變量 x 并給其賦值了初始值,屬于常規(guī)類型推斷。

下面代碼中,變量 x 具有初始值 0,編譯器推斷其類型為 number 類型。

下面代碼中,變量 x 具有初始值 0,但是使用了 const 關(guān)鍵字定義其為常量,故編譯器推斷其類型為字面量類型 0

假如變量聲明時(shí)未指定初始值呢?這時(shí),編譯器將其自動(dòng)推斷為 any 類型。根據(jù)[[子類型兼容性]]章節(jié)中介紹可知,any 類型屬于頂端類型之一,不是任意類型的子類型,但是卻與任意類型滿足賦值兼容性,這樣未指定初始值的變量 x 后面可以被被賦值為任意類型。

最佳通用類型

編譯器在進(jìn)行類型推斷過(guò)程中,有可能推斷出多個(gè)可能得類型,并會(huì)參考所有可能的類型得出最終的最佳通用類型。

這里得出的類型可能為字面量 hello 對(duì)應(yīng)的原始類型 string、字面量 0 對(duì)應(yīng)的原始類型 number,得出的最佳通用類型為 string | number

const list = ['hello', 0]; // (string | number)[]

這里正好解釋了開(kāi)篇提出的問(wèn)題 3

當(dāng)數(shù)組的成員類型存在子類型關(guān)系時(shí),最佳通用類型也會(huì)有所不同。

這里 list1 根據(jù)可能的類型 A、B 得出最佳通用類型為 A | Blist2 所有可能的類型有 A、B、Base,但是存在[[子類型兼容性]]: A <- BaseB <- Base,所以得出的最佳通用類型為 Base。

class Base {
 version: string = '1.0.0'
}
class A extends Base {}
class B extends Base {}
const list1 = [new A(), new B()] // (A | B)[]
const list2 = [new A(), new B(), new Base()] // Base[]

代碼運(yùn)行驗(yàn)證如下:

按上下文歸類

上文說(shuō)的常規(guī)類型推斷、最佳通用類型都是由表達(dá)式的結(jié)果推導(dǎo)對(duì)應(yīng)變量的類型,這是一個(gè)由右向左的推斷過(guò)程。TypeScript 編譯器還能夠由變量的類型來(lái)推導(dǎo)變量對(duì)應(yīng)初始值的類型,這是一個(gè)由左向右的推斷過(guò)程。

這里指定變量 f 為 AddFunction 類型,給定的初始值是一個(gè)函數(shù),并且這個(gè)函數(shù)的形參和返回值都未指定類型,編譯器會(huì)自動(dòng)根據(jù) f 的類型推導(dǎo)出初始值的形參和返回值類型。

interface AddFunction {
    (x: number, y: number): number;
}
let f: AddFunction = (x, y) => {
    return x + y;
}

編譯器按上下文歸類推斷出的類型如下:

類型放寬

上文在介紹最佳通用類型時(shí)提到過(guò)“字面量 hello 對(duì)應(yīng)的原始類型 string”,這就屬于類型放寬。編譯器在進(jìn)行類型推斷時(shí)候會(huì)進(jìn)行類型放寬,比如字面量類型 hello 放寬為原始類型 string。同樣,下面變量 x 也會(huì)被放寬為 number 類型。

let x = 0; // number

類型放寬分為:常規(guī)類型放寬、字面量類型放寬兩類,見(jiàn)下文。

常規(guī)類型放寬

undefinednull 類型會(huì)被編譯器放寬為 any 類型,不過(guò)這一特性在配置的編譯器檢查規(guī)則 --strictNullChecks 不同時(shí)情況不一樣。

非嚴(yán)格類型檢查模式

修改 tsconfig.json 配置文件為如下:

{
 "compilerOptions": {
  "strictNullChecks": false
 }
}
let x1 = undefined; // any
const x2 = undefined; // any
let y1 = null; // any
const y2 = null; // any

此模式下,undefined 的值依然是 undefined 類型(null 同理),只是編譯器在進(jìn)行類型推斷時(shí)將 undefined 類型放寬為了 any 類型。

嚴(yán)格類型檢查模式

修改 tsconfig.json 配置文件為如下:

{
 "compilerOptions": {
  "strictNullChecks": true
 }
}
let x1 = undefined; // undefined
const x2 = undefined; // undefined
let y1 = null; // null
const y2 = null; // null

此模式下,編譯器不會(huì)對(duì) undefined、null 類型進(jìn)行放寬,undefined 的值依然是 undefined 類型(null 同理)。

字面量類型放寬

字面量類型在進(jìn)行類型推斷時(shí),若當(dāng)前表達(dá)式的值是可變的,則會(huì)對(duì)字面量的類型進(jìn)行放寬,放寬規(guī)則如下表。

開(kāi)篇的問(wèn)題 1 中的代碼見(jiàn)下方,定義了兩個(gè)表達(dá)式,之前 let 定義的表達(dá)式值是可變的,const 定義的表達(dá)式值是不可變的。因此,變量 x 類型按照字面量進(jìn)行放寬為 string 類型,變量 y 類型不會(huì)進(jìn)行放寬,為字面量類型 0。

let x = 0;
const y = 0;

對(duì)象、數(shù)組字面量類型的放寬

上文以表達(dá)式的值是否可變的角度來(lái)看待字面量類型是否可以放寬并非十分恰當(dāng),對(duì)于使用 const 關(guān)鍵字定義的對(duì)象、數(shù)組的情況則稍有不同。

JS 中 const 定義的變量不可變指的是變量指向的指針不可變,但是對(duì)象、數(shù)組是引用類型,當(dāng)對(duì)象的屬性或數(shù)組的元素的值變化(或者指向的指針變化)時(shí),該變量的指針并未改變。

因此,對(duì)象、數(shù)組字面量類型在進(jìn)行推斷時(shí)也會(huì)進(jìn)行類型放寬,這正是開(kāi)篇的問(wèn)題 3 的解答。

下面代碼 base.version 的類型會(huì)進(jìn)行放寬,結(jié)果類型為:number,base.author 同樣,放寬為:string。

const base = {
 version: 1,
 author: 'JohnieXu'
};

下面代碼 list 的類型會(huì)進(jìn)行放寬,結(jié)果類型為:(string | number)[]。

const list = ['hello', 0];

類字面量類型的放寬

類字面量和對(duì)象字面量比較相似,因?yàn)樵陬愒?JS 中(或者說(shuō) JS 解釋器)也是通過(guò)對(duì)象進(jìn)行模擬的,不同僅在于類的屬性具有修飾符。對(duì)于具有 readonly 修飾符的對(duì)象屬性,因其值不可變,故不會(huì)進(jìn)行類型放寬。

函數(shù)返回值字面量類型的放寬

在函數(shù)或方法中,若返回值的類型為字面量類型,則編譯器推斷的返回值類型會(huì)放寬;若返回值的類型為字面量聯(lián)合類型,則不會(huì)放寬。

TS 內(nèi)部類型放寬規(guī)則

每個(gè)字面量類型都有一個(gè)內(nèi)置屬性表示其是否可以被放寬,而 TypeScript 編譯器會(huì)根據(jù)放寬規(guī)則來(lái)推斷出這個(gè)內(nèi)置屬性。

在 TypeScript 語(yǔ)言內(nèi)部實(shí)現(xiàn)中,根據(jù)字面量的來(lái)源不同進(jìn)行了分類,來(lái)自于表達(dá)式的字面量類型標(biāo)記為全新的(fresh)字面量類型。只有全新的字面量類型才是可放寬的字面量類型,并且根據(jù)字面量處于表達(dá)式的位置,分為:可變值位置、不可變值位置。

因此,字面量的類型可放寬的充分必要條件為:為全新的字面量類型,且在代碼中處于可變值的位置

實(shí)例分析

以開(kāi)篇的問(wèn)題 4 中部分代碼為例:

const x = 0;
let y = x;

變量 x、y 的類型見(jiàn)下圖,可見(jiàn)兩者類型并不相同,x 類型未放寬,y 類型有放寬。

分析過(guò)程如下:

  • 分析表達(dá)式 const x = 0;
  • 表達(dá)式中字面量 0 為全新的字面量類型
  • 表達(dá)式中使用了 const 關(guān)鍵字,字面量 0 處于不可變值位置,因此推斷 x 類型時(shí)不進(jìn)行類型放寬
  • 變量 x 的類型是:可放寬的數(shù)字字面量類型 0(全新的字面量類型 0)
  • 分析表達(dá)式 let y = x;
  • 表達(dá)式中變量 x 為可放寬的數(shù)字字面量類型 0
  • 表達(dá)式中使用了 let 關(guān)鍵字,變量 x 處于可變值位置,因此推斷 y 類型時(shí)進(jìn)行類型放寬
  • 變量 y 的類型是可放寬的數(shù)字字面量類型 0 的放寬類型,即:number 類型。

下面還是以開(kāi)篇的問(wèn)題 4 中部分代碼為例(說(shuō)明使用了類型注解的場(chǎng)景):

const a: 0 = 0;
let b = a;

變量 a、b 的類型見(jiàn)下圖,可見(jiàn)兩者類型相同,都沒(méi)有類型放寬。

分析過(guò)程如下:

  • 分析表達(dá)式 const a: 0 = 0;
  • 變量 a 的初始值 0 的類型為全新的字面量類型 0,即可放寬的字面量類型 0
  • 但是,這里通過(guò)類型注解 0,指定了變量 a 的類型為字面量類型 0,由于類型注解的字面量類型不是全新的字面量類型,所以變量 a 的類型為不可放寬的字面量類型 0
  • 分析表達(dá)式 let b = a;
  • 這里變量 b 的初始值 a 的類型為不可放寬的字面量類型 0,雖然使用 let 關(guān)鍵字定義讓其處于可變值位置,但是不滿足類型放寬的必要條件,所以變量 b 的類型為不可放寬的字面量類型 0。

開(kāi)篇問(wèn)題解答

開(kāi)篇提出的問(wèn)題中 1、3、4 已在上文講解過(guò)程中進(jìn)行過(guò)分析,這里分析一下問(wèn)題 2 。

function f() {
 return 0
}
let x = f();

先看這個(gè)問(wèn)題的答案,如下:

分析過(guò)程:

  • 函數(shù) f 的返回值類型為字面量類型 0,根據(jù)上文介紹的“函數(shù)返回值類型為字面量類型會(huì)進(jìn)行類型放寬”可知,函數(shù) f 返回值類型為字面量類型 0 放寬的結(jié)果類型:number 類型
  • 分析表達(dá)式 let x = f();
  • 這里變量 x 的初始值是函數(shù) f 的返回值,是 number 類型
  • 表達(dá)式采用了 let 關(guān)鍵字,處于可變值位置,會(huì)對(duì) number 類型進(jìn)行放寬
  • number 類型放寬的結(jié)果類型為自身:number 類型,故變量 x 為 number 類型。

以上就是TS 中的類型推斷與放寬實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于TS類型推斷與放寬的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • requireJS使用指南

    requireJS使用指南

    如今最常用的JavaScript庫(kù)之一是RequireJS。最近我參與的每個(gè)項(xiàng)目,都用到了RequireJS,或者是我向它們推薦了增加RequireJS。在這篇文章中,我將描述RequireJS是什么,以及它的一些基礎(chǔ)場(chǎng)景。&nbsp;
    2016-04-04
  • 使用typeScript 進(jìn)行扁平化數(shù)據(jù)轉(zhuǎn)樹(shù)實(shí)現(xiàn)demo

    使用typeScript 進(jìn)行扁平化數(shù)據(jù)轉(zhuǎn)樹(shù)實(shí)現(xiàn)demo

    這篇文章主要介紹了使用typeScript 進(jìn)行扁平化數(shù)據(jù)轉(zhuǎn)樹(shù)實(shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • TypeScript?中?as?const使用介紹

    TypeScript?中?as?const使用介紹

    這篇文章主要為大家介紹了TypeScript?中?as?const使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • layui中的layer彈出層自定義樣式更改背景

    layui中的layer彈出層自定義樣式更改背景

    layui中的layer彈出層有很多提示框,但是我們使用最多的應(yīng)該就幾種,layer.msg、layer.alert、layer.open、layer.load等。layer?有內(nèi)置的skin:layui-layer-lan,layui-layer-molv,可以直接使用。skin不僅允許你傳入layer內(nèi)置的樣式class名,可以自定義class名。
    2023-06-06
  • 聯(lián)合類型Union?Types與交叉類型Intersection?Types區(qū)別解析

    聯(lián)合類型Union?Types與交叉類型Intersection?Types區(qū)別解析

    這篇文章主要為大家介紹了聯(lián)合類型Union?Types與交叉類型Intersection?Types區(qū)別詳解
    2023-06-06
  • TypeScript數(shù)組實(shí)現(xiàn)棧與對(duì)象實(shí)現(xiàn)棧的區(qū)別詳解

    TypeScript數(shù)組實(shí)現(xiàn)棧與對(duì)象實(shí)現(xiàn)棧的區(qū)別詳解

    這篇文章主要為大家介紹了TypeScript數(shù)組實(shí)現(xiàn)棧與對(duì)象實(shí)現(xiàn)棧的區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Underscore.js常用方法總結(jié)

    Underscore.js常用方法總結(jié)

    這篇文章主要介紹了Underscore.js常用方法總結(jié),本文講解了Underscore.js概述、在node.js下安裝、與集合有關(guān)的方法、與對(duì)象有關(guān)的方法、與函數(shù)相關(guān)的方法等內(nèi)容,需要的朋友可以參考下
    2015-02-02
  • 移動(dòng)設(shè)備web開(kāi)發(fā)首選框架:zeptojs介紹

    移動(dòng)設(shè)備web開(kāi)發(fā)首選框架:zeptojs介紹

    這篇文章主要介紹了移動(dòng)設(shè)備web開(kāi)發(fā)首選框架:zeptojs介紹,他兼容jquery的API,所以學(xué)起來(lái)或用起來(lái)并不吃力,需要的朋友可以參考下
    2015-01-01
  • FastAdmin表單驗(yàn)證data-rule插件—Nice-validator的使用方法

    FastAdmin表單驗(yàn)證data-rule插件—Nice-validator的使用方法

    FastAdmin的表單驗(yàn)證data-rule非常方便,也很炫酷,采用的Nice-validator是一款非常強(qiáng)大的表單驗(yàn)證插件,通過(guò)簡(jiǎn)單在元素上配置規(guī)則,即可達(dá)到驗(yàn)證的效果,怎么使用Nice-validator插件呢
    2023-09-09
  • 基于Javascript實(shí)現(xiàn)頁(yè)面商品個(gè)數(shù)增減功能

    基于Javascript實(shí)現(xiàn)頁(yè)面商品個(gè)數(shù)增減功能

    本文給大家介紹基于Javascript實(shí)現(xiàn)頁(yè)面商品個(gè)數(shù)增減功能,通過(guò)點(diǎn)擊數(shù)量增減個(gè)數(shù),代碼分為前端頁(yè)面,后臺(tái)返回代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2019-07-07

最新評(píng)論