溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

TypeScript 4.1中的模板字面類型是什么

發(fā)布時(shí)間:2021-10-21 14:19:33 來(lái)源:億速云 閱讀:158 作者:iii 欄目:編程語(yǔ)言

這篇文章主要介紹“TypeScript 4.1中的模板字面類型是什么”,在日常操作中,相信很多人在TypeScript 4.1中的模板字面類型是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”TypeScript 4.1中的模板字面類型是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

新的語(yǔ)言特性

模板字面類型

自 ES6 開始,我們就可以通過(guò)模板字面量(Template Literals)的特性,用反引號(hào)來(lái)書寫字符串,而不只是單引號(hào)或雙引號(hào):

const message = `text`;

正如 Flavio Copes 所言,模板字面量提供了之前用引號(hào)寫的字符串所不具備的特性:

  • 定義多行字符串非常方便

  • 可以輕松地進(jìn)行變量和表達(dá)式的插值

  • 可以用模板標(biāo)簽創(chuàng)建 DSL(Domain Specific Language,領(lǐng)域特定語(yǔ)言)

模板字面量類型和 JavaScript 中的模板字符串語(yǔ)法完全一致,只不過(guò)是用在類型定義里面:

type Entity = 'Invoice';  type Notification = `${Entity} saved`; // 等同于 // type Notification = 'Invoice saved';   type Viewport = 'md' | 'xs'; type Device = 'mobile' | 'desktop';  type Screen = `${Viewport | Device} screen`; // 等同于下面這一行 // type Screen = 'md screen' | 'xs screen' | 'mobile screen' | 'desktop screen';

當(dāng)我們定義了一個(gè)具體的字面量類型時(shí),TypeScript 會(huì)通過(guò)拼接內(nèi)容的方式產(chǎn)生新的字符串字面量類型。

鍵值對(duì)類型中鍵的重新映射(Key Remapping)

映射類型可以基于任意鍵創(chuàng)建新的對(duì)象類型。 字符串字面量可以用作映射類型中的屬性名稱:

type Actions = { [K in 'showEdit' | 'showCopy' | 'showDelete']?: boolean; }; // 等同于 type Actions = {   showEdit?:   boolean,   showCopy?:   boolean,   showDelete?: boolean };

如果你想創(chuàng)建新鍵或過(guò)濾掉鍵,TypeScript 4.1 允許你使用新的 as 子句重新映射映射類型中的鍵:

type MappedTypeWithNewKeys<T> = {     [K in keyof T as NewKeyType]: T[K] }

TypeScript Remapping KeysThe new as clause lets you leverage features like  template literal types to easily create new property names based on old ones.  Keys can be filtered by producing never so that you don&rsquo;t have to use an extra  Omit helper type in some cases: 通過(guò)使用新的 as  子句,我們可以利用模板字面量類型之類的特性輕松地基于舊屬性創(chuàng)建新屬性名稱。我們可以通過(guò)輸出 never 來(lái)過(guò)濾鍵,這樣在某些情況下就不必使用額外的 Omit  輔助類型:

type Getters<T> = {     [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] };  interface Person {     name: string;     age: number;     location: string; }  type LazyPerson = Getters<Person>; //   ^ = type LazyPerson = { //       getName: () => string; //       getAge: () => number; //       getLocation: () => string; //   }  // 去掉 'kind' 屬性 type RemoveKindField<T> = {     [K in keyof T as Exclude<K, "kind">]: T[K] };  interface Circle {     kind: "circle";     radius: number; }  type KindlessCircle = RemoveKindField<Circle>; //   ^ = type KindlessCircle = { //       radius: number; //   }

TypeScript 利用帶有 as 子句的模板文字類型 (source)

JSX 工廠函數(shù)

JSX 代表 JavaScript XML,它允許我們使用 JavaScript 編寫 HTML 元素并將其放置在 DOM 中,而無(wú)需任何  createElement() 或 appendChild() 方法,例如:

const greeting = <h5>Yes I can do it!</h5>; ReactDOM.render(greeting, document.getElementById('root'));

TypeScript 4.1 通過(guò)編譯器選項(xiàng) jsx 的兩個(gè)新選項(xiàng)支持 React 17 的 jsx 和 jsxs 工廠函數(shù):

  • react-jsx

  • react-jsxdev

“這些選項(xiàng)分別用于生產(chǎn)和開發(fā)編譯。通常,一個(gè)選項(xiàng)可以擴(kuò)展自另一個(gè)選項(xiàng)?!?&mdash; TypeScript發(fā)版說(shuō)明

以下是兩個(gè)用于生產(chǎn)和開發(fā)的 TypeScript 配置文檔的兩個(gè)示例:

// ./src/tsconfig.json {   "compilerOptions": {     "module": "esnext",     "target": "es2015",     "jsx": "react-jsx",     "strict": true   },   "include": ["./**/*"] }

開發(fā)配置:

// ./src/tsconfig.dev.json {   "extends": "./tsconfig.json",   "compilerOptions": {     "jsx": "react-jsxdev"   } }

如下圖所示,TypeScript 4.1 支持在像 React 這樣的 JSX 環(huán)境中進(jìn)行類型檢查:

TypeScript 4.1中的模板字面類型是什么  

遞歸條件類型

另一個(gè)新增功能是遞歸條件類型,它允許它們?cè)诜种е幸米约?,從而能夠更靈活地處理?xiàng)l件類型,使得編寫遞歸類型別名更加容易。下面是一個(gè)使用 Awaited  展開深層嵌套的 Promise 的示例:

type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;  // 類似 `promise.then(...)`, 但是在類型上更加精確 declare function customThen<T, U>(     p: Promise<T>,     onFulfilled: (value: Awaited<T>) => U ): Promise<Awaited<U>>;

但是應(yīng)當(dāng)注意的是,TypeScript 需要更多時(shí)間來(lái)進(jìn)行遞歸類型的類型檢查。Microsoft 警告,應(yīng)以負(fù)責(zé)任的態(tài)度謹(jǐn)慎使用它們。

Checked indexed accesses 索引訪問(wèn)檢查

_ TypeScript 中的索引簽名允許可以像下面的 Options 接口中那樣訪問(wèn)任意命名的屬性:

interface Options {   path: string;   permissions: number;    // Extra properties are caught by this index signature.   // 額外的屬性將被這個(gè)   [propName: string]: string | number; }  function checkOptions(opts: Options) {   opts.path; // string   opts.permissions; // number    // 這些都可以!因?yàn)轭愋投际?nbsp;string | number   opts.yadda.toString();   opts["foo bar baz"].toString();   opts[Math.random()].toString(); }

在這里,我們看到不是 path 以及 permissions 的屬性應(yīng)具有 string | number 類型:

TypeScript 4.1 提供了一個(gè)新的標(biāo)志 --noUncheckedIndexedAccess,使得每次屬性訪問(wèn)(如  opts.path)或索引訪問(wèn)(如 opts [“ blabla”] )都可能未定義。這意味著如果我們需要訪問(wèn)上一個(gè)示例中的 opts.path  之類的屬性,則必須檢查其是否存在或使用非 null 斷言運(yùn)算符(后綴 ! 字符):

function checkOptions(opts: Options) {   opts.path; // string   opts.permissions; // number    // 以下代碼在 noUncheckedIndexedAccess 開啟時(shí)是非法的   opts.yadda.toString();   opts["foo bar baz"].toString();   opts[Math.random()].toString();    // 檢查屬性是否真的存在   if (opts.yadda) {     console.log(opts.yadda.toString());   }    // 直接使用非空斷言操作符   opts.yadda!.toString(); }

--noUncheckedIndexedAccess 標(biāo)志對(duì)于捕獲很多錯(cuò)誤很有用,但是對(duì)于很多代碼來(lái)說(shuō)可能很嘈雜。 這就是為什么 --strict  開關(guān)不會(huì)自動(dòng)啟用它的原因。

不需要 baseUrl 指定路徑

在 TypeScript 4.1 之前,要能夠使用 tsconfig.json 文件中的 paths,必須聲明 baseUrl 參數(shù)。  在新版本中,可以在不帶 paths 選項(xiàng)的情況下指定 baseUrl。 這解決了自動(dòng)導(dǎo)入中路徑不暢的問(wèn)題。

{     "compilerOptions": {         "baseUrl": "./src",         "paths": {             "@shared": ["@shared/"] // This mapping is relative to "baseUrl"         }     } }

checkJs 默認(rèn)打開 allowJs

如果您有一個(gè) JavaScript 項(xiàng)目,正在其中使用 checkJs 選項(xiàng)檢查 .js 文件中的錯(cuò)誤,則還應(yīng)該聲明 allowJs 以允許編譯  JavaScript 文件。而 TypeScript 4.1 中,默認(rèn)情況下 checkJs 意味著 allowJs:

{   compilerOptions: {     allowJs: true,     checkJs: true   } }

JSDoc @see 標(biāo)簽的編輯器支持

在編輯器中使用 TypeScript 時(shí),現(xiàn)在對(duì) JSDoc 標(biāo)簽 @see 有了更好的支持,這將改善TypeScript 4.1的可用性:

// @filename: first.ts export class C {}  // @filename: main.ts import * as first from "./first";  /**  * @see first.C  */ function related() {}

不兼容改變

lib.d.ts 變動(dòng)

結(jié)構(gòu)和 DOM 的環(huán)境聲明,使您可以輕松地開始編寫經(jīng)過(guò)類型檢查的 JavaScript 代碼。

該文件自動(dòng)包含在 TypeScript 項(xiàng)目的編譯上下文中。 您可以通過(guò)指定 --noLib 編譯器命令行標(biāo)志或在 tsconfig.json 中配置  noLib 為 true 來(lái)排除它。

在 TypeScript 4.1 中,由于 DOM 類型是自動(dòng)生成的,lib.d.ts 可能具有一組變動(dòng)的 API,例如,從 ES2016 中刪除的  Reflect.enumerate。

abstract 成員不能被標(biāo)記為 async

在另一個(gè)重大更改中,標(biāo)記為 abstract 的成員不能被再標(biāo)記為 async。 因此,要修復(fù)您的代碼,必須刪除 async 關(guān)鍵字:

abstract class MyClass {   // 在 TypeScript 4.1 中必須刪除 async   abstract async create(): Promise<string>; }

any/unknown 向外傳播

在 TypeScript 4.1 之前,對(duì)于像 foo && somethingElse 這樣的表達(dá)式, foo 的類型是 any 或  unknown。 整個(gè)表達(dá)式的類型將是 somethingElse 的類型,在以下示例中就是 {someProp:string} :

declare let foo: unknown; declare let somethingElse: { someProp: string }; let x = foo && somethingElse;

在 TypeScript 4.1 中, any 和 unknown 都將向外傳播,而不是在右側(cè)傳播。通常,這個(gè)變更合適的解決方法是從 foo  && someExpression 切換到 !!foo && someExpression。

  • 注意:雙重感嘆號(hào)(!!)是將變量強(qiáng)制轉(zhuǎn)換為布爾值(真或假)的一種簡(jiǎn)便方法。

Promise 中 resolve 的參數(shù)不再是可選類型

Promise 中 resolve 的參數(shù)不再是可選的,例如下面的代碼:

new Promise((resolve) => {   doSomethingAsync(() => {     doSomething();     resolve();   }); });

這段代碼在 TypeScript 4.1 中編譯會(huì)報(bào)錯(cuò):

resolve()   ~~~~~~~~~ error TS2554: Expected 1 arguments, but got 0.   An argument for 'value' was not provided.

要解決這個(gè)問(wèn)題,必須在 Promise 中給 resolve 提供至少一個(gè)值,否則,在確實(shí)需要不帶參數(shù)的情況下調(diào)用 resolve()  的情況下,必須使用顯式的 void 泛型類型參數(shù)聲明 Promise:

new Promise<void>((resolve) => {   doSomethingAsync(() => {     doSomething();     resolve();   }); });

條件展開將會(huì)創(chuàng)建可選屬性

在 JavaScript 中,展開運(yùn)算符 { ...files } 不會(huì)作用于假值,例如 files 為 null 或者 undefined。

在以下使用條件傳播的示例中,如果定義了 file,則將傳播 file.owner 的屬性。否則,不會(huì)將任何屬性傳播到返回的對(duì)象中:

function getOwner(file?: File) {   return {     ...file?.owner,     defaultUserId: 123,   }; }

在TypeScript 4.1之前, getOwner 返回基于每個(gè)展開對(duì)象的聯(lián)合類型:

{ x: number } | { x: number, name: string, age: number, location: string }
  • 如果定義了 file,則會(huì)擁有來(lái)自Person(所有者的類型)的所有屬性。

  • 否則,結(jié)果中一個(gè)都不會(huì)展示

但是事實(shí)證明,這樣的代價(jià)最終會(huì)變得非常高昂,而且通常無(wú)濟(jì)于事。在單個(gè)對(duì)象中存在數(shù)百個(gè)展開對(duì)象,每個(gè)展開對(duì)象都可能增加數(shù)百或數(shù)千個(gè)屬性。  為了更好的性能,在TypeScript 4.1中,返回的類型有時(shí)使用全部可選屬性:

{     x:         number;     name?:     string;     age?:      number;     location?: string; }

不匹配的參數(shù)將不再關(guān)聯(lián)

過(guò)去,彼此不對(duì)應(yīng)的參數(shù)在 TypeScript 中通過(guò)將它們與 any 類型關(guān)聯(lián)而彼此關(guān)聯(lián)。

在下面的重載示例(為同一功能提供多種功能類型)中, pickCard 函數(shù)將根據(jù)用戶傳入的內(nèi)容返回兩個(gè)不同的內(nèi)容。如果用戶傳入表示 deck  的對(duì)象,則該函數(shù)將選擇 card。 如果用戶選擇了 card,他們將得到他們選擇的 card:

let suits = ["hearts", "spades", "clubs", "diamonds"];  function pickCard(x: { suit: string; card: number }[]): number; function pickCard(x: number): { suit: string; card: number }; function pickCard(x: any): any {   // Check to see if we're working with an object/array   // if so, they gave us the deck and we'll pick the card   if (typeof x == "object") {     let pickedCard = Math.floor(Math.random() * x.length);     return pickedCard;   }   // Otherwise just let them pick the card   else if (typeof x == "number") {     let pickedSuit = Math.floor(x / 13);     return { suit: suits[pickedSuit], card: x % 13 };   } }  let myDeck = [   { suit: "diamonds", card: 2 },   { suit: "spades", card: 10 },   { suit: "hearts", card: 4 }, ];  let pickedCard1 = myDeck[pickCard(myDeck)]; alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);  let pickedCard2 = pickCard(15); alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

使用 TypeScript 4.1,某些情況下賦值將會(huì)失敗,而某些情況下的重載解析則將失敗。解決方法是,最好使用類型斷言來(lái)避免錯(cuò)誤。

到此,關(guān)于“TypeScript 4.1中的模板字面類型是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI