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

詳解TS數(shù)字分隔符和更嚴(yán)格的類屬性檢查

 更新時(shí)間:2021年05月06日 15:07:34   作者:淺笑·  
這篇文章主要介紹了TS數(shù)字分隔符和更嚴(yán)格的類屬性檢查,對(duì)TS感興趣的同學(xué),可以參考下

概述

TypeScript 2.4 為標(biāo)識(shí)符實(shí)現(xiàn)了拼寫糾正機(jī)制。即使咱們稍微拼錯(cuò)了一個(gè)變量、屬性或函數(shù)名,TypeScript 在很多情況下都可以提示正確的拼寫。

TypeScript 2.7 支持 ECMAScript 的數(shù)字分隔符提案。 這個(gè)特性允許用戶在數(shù)字之間使用下劃線(_)來(lái)對(duì)數(shù)字分組(就像使用逗號(hào)和點(diǎn)來(lái)對(duì)數(shù)字分組那樣)。

const worldPopulationIn2017 = 7_600_000_000;
const leastSignificantByteMask = 0b1111_1111;
const papayawhipColorHexCode = 0xFF_EF_D5;

數(shù)字分隔符不會(huì)改變數(shù)字字面量的值,但分組使人們更容易一眼就能讀懂?dāng)?shù)字。

這些分隔符對(duì)于二進(jìn)制和十六進(jìn)制同樣有用。

let bits = 0b0010_1010;
let routine = 0xC0FFEE_F00D_BED;
let martin = 0xF0_1E_

注意,可能有些反常識(shí),js里的數(shù)字表示信用卡和電話號(hào)并不適當(dāng),這種情況下使用字符串更好。

當(dāng)咱們將target設(shè)置為es2015編譯的上述代碼時(shí),TypeScript 將生成以下js代碼:

const worldPopulationIn2017 = 7600000000;
const leastSignificantByteMask = 255;
const papayawhipColorHexCode = 16773077;

in操作符細(xì)化和精確的 instanceof

TypeScript 2.7帶來(lái)了兩處類型細(xì)化方面的改動(dòng) - 通過(guò)執(zhí)行“類型保護(hù)”確定更詳細(xì)類型的能力。

首先,instanceof操作符現(xiàn)在利用繼承鏈而非依賴于結(jié)構(gòu)兼容性, 能更準(zhǔn)確地反映出 instanceof操作符在運(yùn)行時(shí)的行為。 這可以幫助避免一些復(fù)雜的問(wèn)題,當(dāng)使用 instanceof去細(xì)化結(jié)構(gòu)上相似(但無(wú)關(guān))的類型時(shí)。

其次,in操作符現(xiàn)在做為類型保護(hù)使用,會(huì)細(xì)化掉沒(méi)有明確聲明的屬性名。

interface A { a: number };
interface B { b: string };

function foo(x: A | B) {
    if ("a" in x) {
        return x.a;
    }
    return x.b;
}

更智能的對(duì)象字面量推斷

在 JS 里有一種模式,用戶會(huì)忽略掉一些屬性,稍后在使用的時(shí)候那些屬性的值為undefined。

let foo = someTest ? { value: 42 } : {};

在以前TypeScript會(huì)查找{ value: number }和{}的最佳超類型,結(jié)果是{}。 這從技術(shù)角度上講是正確的,但并不是很有用。

從2.7版本開始,TypeScript 會(huì)“規(guī)范化”每個(gè)對(duì)象字面量類型記錄每個(gè)屬性, 為每個(gè)undefined類型屬性插入一個(gè)可選屬性,并將它們聯(lián)合起來(lái)。

在上例中,foo的最類型是{ value: number } | { value?: undefined }。 結(jié)合了 TypeScript 的細(xì)化類型,這讓咱們可以編寫更具表達(dá)性的代碼且 TypeScript 也可理解。 看另外一個(gè)例子:

// Has type
//  | { a: boolean, aData: number, b?: undefined }
//  | { b: boolean, bData: string, a?: undefined }
let bar = Math.random() < 0.5 ?
    { a: true, aData: 100 } :
    { b: true, bData: "hello" };

if (bar.b) {
    // TypeScript now knows that 'bar' has the type
    //
    //   '{ b: boolean, bData: string, a?: undefined }'
    //
    // so it knows that 'bData' is available.
    bar.bData.toLowerCase()
}

這里,TypeScript 可以通過(guò)檢查b屬性來(lái)細(xì)化bar的類型,然后允許我們?cè)L問(wèn)bData屬性。

unique symbol 類型和常量名屬性

TypeScript 2.7 對(duì)ECMAScript里的symbols有了更深入的了解,你可以更靈活地使用它們。

一個(gè)需求很大的用例是使用symbols來(lái)聲明一個(gè)類型良好的屬性。 比如,看下面的例子:

const Foo = Symbol("Foo");
const Bar = Symbol("Bar");

let x = {
    [Foo]: 100,
    [Bar]: "hello",
};

let a = x[Foo]; // has type 'number'
let b = x[Bar]; // has type 'string'

可以看到,TypeScript 可以追蹤到x擁有使用符號(hào)Foo和Bar聲明的屬性,因?yàn)镕oo和Bar被聲明成常量。 TypeScript 利用了這一點(diǎn),讓Foo和Bar具有了一種新類型:unique symbols。

unique symbols是symbols的子類型,僅可通過(guò)調(diào)用Symbol()或Symbol.for()或由明確的類型注釋生成。 它們僅出現(xiàn)在常量聲明和只讀的靜態(tài)屬性上,并且為了引用一個(gè)存在的unique symbols類型,你必須使用typeof操作符。 每個(gè)對(duì)unique symbols的引用都意味著一個(gè)完全唯一的聲明身份。

// Works
declare const Foo: unique symbol;

// Error! 'Bar' isn't a constant.
let Bar: unique symbol = Symbol();

// Works - refers to a unique symbol, but its identity is tied to 'Foo'.
let Baz: typeof Foo = Foo;

// Also works.
class C {
    static readonly StaticSymbol: unique symbol = Symbol();
}

因?yàn)槊總€(gè)unique symbols都有個(gè)完全獨(dú)立的身份,因此兩個(gè)unique symbols類型之前不能賦值和比較。

const Foo = Symbol();
const Bar = Symbol();

// Error: can't compare two unique symbols.
if (Foo === Bar) {
    // ...
}

另一個(gè)可能的用例是使用 symbols做為聯(lián)合標(biāo)記。

// ./ShapeKind.ts
export const Circle = Symbol("circle");
export const Square = Symbol("square");

// ./ShapeFun.ts
import * as ShapeKind from "./ShapeKind";

interface Circle {
    kind: typeof ShapeKind.Circle;
    radius: number;
}

interface Square {
    kind: typeof ShapeKind.Square;
    sideLength: number;
}

function area(shape: Circle | Square) {
    if (shape.kind === ShapeKind.Circle) {
        // 'shape' has type 'Circle'
        return Math.PI * shape.radius ** 2;
    }
    // 'shape' has type 'Square'
    return shape.sideLength ** 2;
}

更嚴(yán)格的類屬性檢查

TypeScript 2.7 引入了一個(gè)新的編譯器選項(xiàng),用于類中嚴(yán)格的屬性初始化檢查。如果啟用了--strictPropertyInitialization標(biāo)志,則類型檢查器將驗(yàn)證類中聲明的每個(gè)實(shí)例屬性

  • 是否有包含undefined的類型
  • 有一個(gè)明確的初始值設(shè)定項(xiàng)
  • 在構(gòu)造函數(shù)中被明確賦值

--strictPropertyInitialization選項(xiàng)是編譯器選項(xiàng)系列的一部分,當(dāng)設(shè)置--strict標(biāo)志時(shí),該選項(xiàng)會(huì)自動(dòng)啟用。 與所有其他嚴(yán)格的編譯器選項(xiàng)一樣,咱們可以將--strict設(shè)置為true,并通過(guò)將--strictPropertyInitialization設(shè)置為false來(lái)有選擇地退出嚴(yán)格的屬性初始化檢查。

請(qǐng)注意,必須設(shè)置--strictNullCheck標(biāo)志(通過(guò)—strict直接或間接地設(shè)置),以便--strictPropertyInitialization起作用。

現(xiàn)在,來(lái)看看嚴(yán)格的屬性初始化檢查。如果沒(méi)有啟用--strictpropertyinitialized標(biāo)志,下面的代碼類型檢查就可以了,但是會(huì)在運(yùn)行時(shí)產(chǎn)生一個(gè)TypeError錯(cuò)誤:

class User {
  username: string;
}

const user = new User();

// TypeError: Cannot read property 'toLowerCase' of undefined
const username = user.username.toLowerCase();

出現(xiàn)運(yùn)行時(shí)錯(cuò)誤的原因是,username屬性值為undefined,因?yàn)闆](méi)有對(duì)該屬性的賦值。因此,對(duì)toLowerCase()方法的調(diào)用失敗。

如果啟用——strictpropertyinitialize,類型檢查器將會(huì)報(bào)一個(gè)錯(cuò)誤:

class User {
  // Type error: Property 'username' has no initializer
  // and is not definitely assigned in the constructor
  username: string;
}

接下來(lái),看看四種不同的方法,可以正確地輸入U(xiǎn)ser類來(lái)消除類型錯(cuò)誤。

解決方案1:允許定義

消除類型錯(cuò)誤的一種方法是為username屬性提供一個(gè)包含undefined的類型:

class User {
  username: string | undefined;
}

const user = new User();

現(xiàn)在,username屬性保存undefined的值是完全有效的。但是,當(dāng)咱們想要將username屬性用作字符串時(shí),首先必須確保它實(shí)際包含的是字符串而不是undefined的值,例如使用typeof

// OK
const username = typeof user.username === "string"
  ? user.username.toLowerCase()
  : "n/a";

解決方案2:顯式屬性初始化

消除類型錯(cuò)誤的另一種方法是向username屬性添加顯式初始化。通過(guò)這種方式,屬性將立即保存一個(gè)字符串值,并且不會(huì)明顯的undefined:

class User {
  username = "n/a";
}

const user = new User();

// OK
const username = user.username.toLowerCase();

解決方案3: 使用構(gòu)造函數(shù)賦值

也許最有用的解決方案是將username參數(shù)添加到構(gòu)造函數(shù)中,然后將其分配給username屬性。這樣,每當(dāng)構(gòu)造User類的實(shí)例時(shí),調(diào)用者必須提供用戶名作為參數(shù):

class User {
  username: string;

  constructor(username: string) {
    this.username = username;
  }
}

const user = new User("mariusschulz");

// OK
const username = user.username.toLowerCase();

咱們 還可以通過(guò)刪除對(duì)類字段的顯式賦值并將public修飾符添加到username構(gòu)造函數(shù)參數(shù)來(lái)簡(jiǎn)化User類,如下所示:

class User {
  constructor(public username: string) {}
}

const user = new User("mariusschulz");

// OK
const username = user.username.toLowerCase();

請(qǐng)注意,嚴(yán)格的屬性初始化要求在構(gòu)造函數(shù)中所有可能的代碼路徑中明確分配每個(gè)屬性。 因此,以下代碼類型不正確,因?yàn)樵谀承┣闆r下,我們將username屬性賦值為未初始化狀態(tài):

class User {
  // Type error: Property 'username' has no initializer
  // and is not definitely assigned in the constructor.
  username: string;

  constructor(username: string) {
    if (Math.random() < 0.5) {
      this.username = username;
    }
  }
}

解決方案4:明確的賦值斷言

如果類屬性既沒(méi)有顯式初始化,也沒(méi)有undefined的類型,則類型檢查器要求直接在構(gòu)造函數(shù)中初始化該屬性;否則,嚴(yán)格的屬性初始化檢查將失敗。如果咱們希望在幫助方法中初始化屬性,或者讓依賴項(xiàng)注入框架來(lái)初始化屬性,那么這是有問(wèn)題的。在這些情況下,咱們必須將一個(gè)明確的賦值斷言(!)添加到該屬性的聲明中:

class User {
  username!: string;

  constructor(username: string) {
    this.initialize(username);
  }

  private initialize(username: string) {
    this.username = username;
  }
}

const user = new User("mariusschulz");

// OK
const username = user.username.toLowerCase();

通過(guò)向username屬性添加一個(gè)明確的賦值斷言,這會(huì)告訴類型檢查器,期望對(duì)username屬性進(jìn)行初始化,即使它自己無(wú)法檢測(cè)到這一點(diǎn)?,F(xiàn)在咱們的責(zé)任是確保在構(gòu)造函數(shù)返回后明確地將屬性賦值給它,所以必須小心;否則,username屬性可能被明顯的undefined或者在運(yùn)行時(shí)就會(huì)報(bào)TypeError錯(cuò)誤。

顯式賦值斷言

盡管咱們嘗試將類型系統(tǒng)做的更富表現(xiàn)力,但我們知道有時(shí)用戶比TypeScript更加了解類型。

上面提到過(guò),顯式賦值斷言是一個(gè)新語(yǔ)法,使用它來(lái)告訴 TypeScript 一個(gè)屬性會(huì)被明確地賦值。 但是除了在類屬性上使用它之外,在TypeScript 2.7里你還可以在變量聲明上使用它!

let x!: number[];
initialize();
x.push(4);

function initialize() {
    x = [0, 1, 2, 3];
}

假設(shè)我們沒(méi)有在x后面加上感嘆號(hào),那么TypeScript會(huì)報(bào)告x從未被初始化過(guò)。 它在延遲初始化或重新初始化的場(chǎng)景下很方便使用。

以上就是詳解TS數(shù)字分隔符和更嚴(yán)格的類屬性檢查的詳細(xì)內(nèi)容,更多關(guān)于TS的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論