自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

TypeScript 5.0 beta 發(fā)布:新版 ES 裝飾器、泛型參數(shù)的常量修飾、枚舉增強(qiáng)等

開(kāi)發(fā) 前端
由于 beta 版本與正式版本通常不會(huì)有明顯的差異,這一系列通常只會(huì)介紹 beta 版本而非正式版本。

TypeScript 已于 2023.01.26 發(fā)布 5.0 beta 版本,你可以在 5.0 Iteration Plan 查看所有被包含的 Issue 與 PR。如果想要搶先體驗(yàn)新特性,執(zhí)行:

$ npm install typescript@beta

來(lái)安裝 beta 版本的 TypeScript,或在 VS Code 中安裝 JavaScript and TypeScript Nightly 來(lái)更新內(nèi)置的 TypeScript 支持。

本篇是筆者的第六篇 TypeScript 更新日志,上一篇是 「TypeScript 4.9 beta 發(fā)布:鴿置的 ES 裝飾器、satisfies 操作符、類型收窄增強(qiáng)、單文件級(jí)別配置等」,你可以在此賬號(hào)的創(chuàng)作中找到(或在掘金/知乎搜索林不渡),接下來(lái)筆者也將持續(xù)更新 TypeScript 的 DevBlog 相關(guān),感謝你的閱讀。

另外,由于 beta 版本與正式版本通常不會(huì)有明顯的差異,這一系列通常只會(huì)介紹 beta 版本而非正式版本。

補(bǔ)充說(shuō)明:TypeScript 并不使用 Semantic Version 規(guī)范,這意味著你不能將 x.0 作為一個(gè) Major 版本——因?yàn)樗赡懿⒉话茐男愿?,你也不能?5.x 作為一個(gè) Minor 版本——因?yàn)樗赡芫桶茐男愿隆?/p>

ECMASCript 裝飾器

ES 新版裝飾器終于在 5.0 中成功 Landing(部分關(guān)于其后續(xù)迭代的討論,請(qǐng)參考 #50820),以下對(duì)新版裝飾器 API 的介紹來(lái)自于筆者此前發(fā)表的 ECMAScript 雙月報(bào)告:裝飾器提案進(jìn)入 Stage 3 。

一個(gè)最基本的裝飾器類型定義大致是這樣的:

type Decorator = (value: Input, context: {
kind: string;
name: string | symbol;
access: {
get?(): unknown;
set?(value: unknown): void;
};
isPrivate?: boolean;
isStatic?: boolean;
addInitializer?(initializer: () => void): void;
}) => Output | void;

value 為這個(gè)裝飾器應(yīng)用處的類或類成員的值,而 context 則包含了這一被裝飾的值的上下文信息。這兩個(gè)參數(shù)都基于裝飾器實(shí)際應(yīng)用的位置來(lái)決定,如果裝飾器的調(diào)用返回了一個(gè)值(Output),那么被裝飾位置的值會(huì)被這個(gè)返回值替換掉。

對(duì)于 context 參數(shù),我們先對(duì)其內(nèi)部的屬性做一個(gè)簡(jiǎn)單介紹:

  • kind,被裝飾的值的類型,如 'class' / 'method' / 'field' 等,這一屬性可以被用來(lái)校驗(yàn)裝飾器被應(yīng)用在了正確的位置,或者在同一個(gè)裝飾器中,基于實(shí)際應(yīng)用位置執(zhí)行不同的裝飾邏輯。
  • name,被裝飾的值的名稱,如類名、屬性名、方法名等。
  • access,其包含了這個(gè)值的 getter 與 setter,我們會(huì)在下面詳細(xì)介紹。
  • isStatic 與 isPrivate,在裝飾器應(yīng)用于類成員時(shí)提供這一成員的訪問(wèn)性修飾符信息。
  • addInitializer,可以通過(guò)這個(gè)屬性添加要在類實(shí)例化時(shí)執(zhí)行的邏輯。

需要注意的是,除了語(yǔ)義與參數(shù)的變化,新版的裝飾器在調(diào)用語(yǔ)法上也進(jìn)行了一些調(diào)整:

  • 類表達(dá)式現(xiàn)在也可以應(yīng)用裝飾器了,如:
const Foo = @deco class {
constructor() {}
}
  • 裝飾器與 export 關(guān)鍵字一同應(yīng)用的方式調(diào)整為:
export default @deco class Foo { }

以下基于當(dāng)前的裝飾器類型,對(duì)裝飾器的基本能力進(jìn)行簡(jiǎn)要介紹,類型定義來(lái)自于 5.0.0 beta 版本中的 lib.decorator.d.ts? 聲明文件,為了可讀性進(jìn)行了略微修改。另外,context.access 屬性目前暫時(shí)被禁用,正在等待 #494 的討論得出結(jié)果。

類裝飾器

類裝飾器的類型定義如下:

type ClassDecorator = (value: Function, context: {
kind: "class";
name: string | undefined;
addInitializer(initializer: (this: Class) => void): void;
}) => Function | void;

value 為被裝飾的 Class,你可以通過(guò)返回一個(gè)新的 Class 來(lái)完全替換掉原來(lái)的 Class?;蛘哂捎谀隳苣玫皆鹊?Class,你也可以直接返回一個(gè)它的子類:

function logged(value, { kind, name }) {
if (kind === "class") {
return class extends value {
constructor(...args) {
super(...args);
}
}
}
}

@logged
class C {}

類方法裝飾器

類方法裝飾器的類型定義如下:

type ClassMethodDecorator = (value: Function, context: {
kind: "method";
name: string | symbol;
static: boolean;
private: boolean;
addInitializer(initializer: (this: This) => void): void;
}) => Function | void;

其 value 參數(shù)為被裝飾的類方法,可以通過(guò)返回一個(gè)新的方法來(lái)直接在原型層面代替掉原來(lái)的方法(對(duì)于靜態(tài)方法則在 Class 的層面替換)?;蛘吣阋部梢园@個(gè)原來(lái)的方法,執(zhí)行一些額外的邏輯:

function logged(value, { kind, name }) {
if (kind === "method") {
return function (...args) {
const ret = value.call(this, ...args);
return ret;
};
}
}

class C {
@logged
m(arg) {}
}

類屬性裝飾器

類屬性裝飾器的類型定義如下:

type ClassFieldDecorator = (value: undefined, context: {
kind: "field";
name: string | symbol;
access: { get(): unknown, set(value: unknown): void };
isStatic: boolean;
isPrivate: boolean;
}) => (initialValue: unknown) => unknown | void;

不同于上面的幾種裝飾器,屬性裝飾器的 value 并不是被裝飾的屬性的值,而是一個(gè) undefined。如果要獲取被裝飾的屬性值,你可以讓屬性裝飾器返回一個(gè)函數(shù),這個(gè)函數(shù)會(huì)在屬性被賦值時(shí)調(diào)用,拿到初始值作為入?yún)?,并可以返回一個(gè)新的值作為實(shí)際的賦值。

function logged(value, { kind, name }) {
if (kind === "field") {
return function (initialValue) {
return 599;
};
}

// ...
}

class C {
@logged x = 1;
}

new C().x; // 599

屬性訪問(wèn)器裝飾器與 Auto Accessor 的介紹請(qǐng)參考上面的 TC39 會(huì)議報(bào)告,這里不再展開(kāi)。同時(shí),目前新版裝飾器中并不存在參數(shù)裝飾器。

如果你想了解更多新版裝飾器的實(shí)際使用,可以參考 with-new-decorators,其中包括了使用 Babel 和 TypeScript 5.0 中的新版裝飾器應(yīng)用。

另外,你也可以參考 Mustard,這是一個(gè)基于新版裝飾器,不依賴元數(shù)據(jù)的命令行應(yīng)用構(gòu)建庫(kù)(Command Line App Builder),它的使用大概是這樣的:

import { MustardFactory, MustardUtils } from "mustard-cli";
import { RootCommand, Option, App, Utils, Input } from "mustard-cli/decorator";
import { CommandStruct, MustardApp } from "mustard-cli/cli";

type Template = "typescript" | "javascript";

@RootCommand()
class RootCommandHandle implements CommandStruct {
@Option("dry", "d", "dry run command to see what will happen")
public dry = false;

@Option("template", "t", "template to use")
public template: Template = "typescript";

@Input("directory to create the project in")
public dir: string = "./";

@Utils()
public utils!: MustardUtils;

public run(): void {
console.log(this.utils.colors.green("Hello World"));
}
}

@App({
name: "awesome-mustard-app",
commands: [RootCommandHandle],
})
class Project implements MustardApp {
onError(error: Error): void {
console.log(error);
}
}

MustardFactory.init(Project).start();

以上的應(yīng)用構(gòu)建了一個(gè)使用 awesome-mustard-app 作為命令的 CLI 應(yīng)用,它的調(diào)用方式是這樣的:

$ create-awesome-app my-awesome-app --dry --template=typescript

如果你想體驗(yàn)一下 Mustard CLI,可以執(zhí)行以下命令:

$ pnpx create-mustard-app

$ cd mustard-app
$ npm install
$ npm run dev

目前 Mustard 仍在進(jìn)一步完善中,文檔 也仍在編寫中,歡迎隨手點(diǎn)個(gè) star ~

另外一點(diǎn)關(guān)于新版裝飾器需要說(shuō)明的是,舊版裝飾器的好伙伴反射元數(shù)據(jù)(Reflect Metadata)目前并不支持與新版裝飾器一同使用,筆者的猜想是反射元數(shù)據(jù)提案可能會(huì)在 3 月或更晚的 TC39 會(huì)議上進(jìn)行討論,大概率也需要進(jìn)行數(shù)輪修改才能推進(jìn)到 Stage 3。因此,如果你想提前開(kāi)始使用新版裝飾器,短期內(nèi)是指望不了元數(shù)據(jù)能力的。

然而我們知道,元數(shù)據(jù)是基于裝飾器實(shí)現(xiàn)依賴注入的重要手段,基于舊版裝飾器的框架基本都是一個(gè)套路:類的成員注入元數(shù)據(jù),然后由工廠方法在實(shí)例化這個(gè)類的同時(shí)按照元數(shù)據(jù)來(lái)初始化成員。比如使用裝飾器的 NodeJs 框架中會(huì)這么寫:

@Controller('/user')
class UserController {
@Inject()
userService: UserService;

@Get('/query')
async queryUser() { }

@Post('/create')
async addUser() { }
}

UserService? 會(huì)作為類型的元數(shù)據(jù)被注入到 userService? 上,并在實(shí)例化時(shí)注入一個(gè) UserService 實(shí)例。同時(shí) queryUser 和 addUser 會(huì)分別被注冊(cè)為 GET /query? 和 POST /create? 的請(qǐng)求處理方法。缺少了元數(shù)據(jù)的類型信息注入,在新版裝飾器中我們暫時(shí)無(wú)法優(yōu)雅地實(shí)現(xiàn) UserService? 到 userService 的注入。

而在 Mustard 中,我們的應(yīng)用場(chǎng)景暫時(shí)不依賴類型信息來(lái)實(shí)現(xiàn)實(shí)例屬性注入,而是只需要做命令行參數(shù)到屬性名的映射,然后將值注入即可。我們使用了 context.addInitializer,將裝飾器收集到的屬性名、初始值等信息強(qiáng)行替換掉實(shí)例內(nèi)的屬性值,再由工廠方法按照這個(gè) Initializer 描述來(lái)真正進(jìn)行實(shí)例的初始化。

最后,舊版的 --experimentalDecorators 選項(xiàng)將會(huì)仍然保留,如果啟用此配置,則仍然會(huì)將裝飾器視為舊版,新版的裝飾器無(wú)需任何配置就能夠默認(rèn)啟用。

泛型參數(shù)的常量修飾

在此前,函數(shù)中的泛型參數(shù)推導(dǎo)只能推導(dǎo)到基礎(chǔ)類型一級(jí)(即比字面量類型高出一個(gè)層級(jí)的類型),如 string? 、string[] 這樣:

declare function foo<T>(x: T): T;

foo('linbudu'); // string
foo([1, 2, 3]); // <number[]
// { name: string; techs: string[]; }
foo({ name: 'linbudu', techs: ['nodejs', 'typescript', 'graphql'] });

這其實(shí)類似于使用 let 聲明變量時(shí)的自動(dòng)類型推導(dǎo)表現(xiàn)。

TypeScript 5.0 新增了對(duì)泛型參數(shù)的常量修飾(基本等價(jià)于常量斷言),被修飾的泛型參數(shù)在進(jìn)行類型信息推導(dǎo)時(shí),將推導(dǎo)到盡可能精確的字面量類型層級(jí):

declare function foo<const T>(x: T): T;

foo('linbudu'); // 'linbudu'
foo([1, 2, 3]); // readonly [1, 2, 3]
// { name: 'linbudu'; techs: readonly ['nodejs', 'typescript', 'graphql'] }
foo({ name: 'linbudu', techs: ['nodejs', 'typescript', 'graphql'] });

// 如果不使用常量修飾,等價(jià)于此效果
foo({ name: 'linbudu', techs: ['nodejs', 'typescript', 'graphql'] } as const);

可以看到這里對(duì)于數(shù)組類型的類型推斷,其實(shí)基本等價(jià)于常量斷言后的類型:每一級(jí)的數(shù)組類型都加上了 readonly 修飾。

當(dāng)被常量修飾的泛型參數(shù)為數(shù)組類型時(shí),如果其泛型約束不包含 readonly,則推導(dǎo)出的類型將回歸到泛型約束來(lái)維持其可變狀態(tài),否則才會(huì)是預(yù)期的常量推導(dǎo):

declare function foo<const T extends readonly string[]>(args: T): T;

declare function bar<const T extends string[]>(args: T): T;

// [readonly ["a", "b", "c"]
foo(["a", "b" ,"c"]);
// string[]
bar(["a", "b" ,"c"]);

枚舉增強(qiáng)

TypeScript 5.0 中對(duì)枚舉進(jìn)行了一次全面的能力增強(qiáng),移除了此前諸如「枚舉計(jì)算成員必須位于字面量成員之后」、「僅允許在數(shù)字枚舉中定義計(jì)算成員」、「常量枚舉中不允許包含變量或表達(dá)式」的限制:

const BaseValue = 10;
const Prefix = "/data";

enum Values {
First = BaseValue,
// 此前會(huì)提示「枚舉成員必須具有初始化表達(dá)式」,現(xiàn)在會(huì)正確從 10 開(kāi)始累加
Second,
Third,
}
enum Routes {
// 此前會(huì)提示「只有數(shù)字枚舉可具有計(jì)算成員,但此表達(dá)式的類型為“string”」
Parts = `${Prefix}/parts`,
Invoices = `${Prefix}/invoices`,
}

const enum ConstValues {
// 此前會(huì)提示「常量枚舉成員初始值設(shè)定項(xiàng)只能包含字面量值和其他計(jì)算的枚舉值」
First = BaseValue, // 10
Second, // 11
Third, // 12
}
const enum ConstRoutes {
// 此前會(huì)提示「常量枚舉成員初始值設(shè)定項(xiàng)只能包含字面量值和其他計(jì)算的枚舉值」
Parts = `${Prefix}/parts`, // "/data/parts"
Invoices = `${Prefix}/invoices`, // "/data/invoices"
}

這一變化的主要原因在于,此前 TypeScript 中存在數(shù)字枚舉和字符串枚舉兩種類型的枚舉,其中數(shù)字枚舉僅允許數(shù)字類型與計(jì)算屬性成員,不允許字符串類型,而字符串枚舉又僅允許數(shù)字或字符串枚舉成員:

const BaseValue = 10;
const Prefix = '/data';

enum Values {
First = BaseValue,
// 枚舉成員必須具有初始化表達(dá)式。
Second,
Third,
}
enum Routes {
// 只有數(shù)字枚舉可具有計(jì)算成員,但此表達(dá)式的類型為“string”。
Parts = `${Prefix}/parts`,
Invoices = `${Prefix}/invoices`,
}

而在 5.0 版本中將這兩種枚舉合并成了單一的、功能更強(qiáng)大的枚舉類型,其成員允許任何常量或表達(dá)式計(jì)算,并僅為常量成員賦予字符串。同時(shí),現(xiàn)在一個(gè)枚舉類型將被視為其所有成員類型組成的聯(lián)合類型,如偽代碼 type Enum = Enum.A | Enum.B | Enum.C。

--verbatimModuleSyntax 配置

我們知道,TS 文件到 JS 文件的編譯過(guò)程主要包括三件事:類型信息擦除、語(yǔ)法降級(jí)、聲明文件生成。關(guān)于類型信息擦除,你應(yīng)該能立刻想到包括類型定義和類型簽名,但實(shí)際上這里還包含著常常被忽略的類型導(dǎo)入。

import { User } from './user.model';

const user: User = {};

在這個(gè)例子中,我們很容易確定 User 只被作為類型使用,需要被移除(否則如果運(yùn)行時(shí)不存在一個(gè) User Class,就會(huì)出錯(cuò)了),那么,如果 user.model.ts 中有這么一行代碼:

// 額外的副作用
setupUserModelMiddleware();

export class User {};

這個(gè)時(shí)候,如果把導(dǎo)入語(yǔ)句移除,可能就會(huì)導(dǎo)致代碼運(yùn)行時(shí)出現(xiàn)異常。

一直以來(lái),為了避免對(duì)導(dǎo)入語(yǔ)句的移除影響運(yùn)行時(shí)代碼,TypeScript 使用了多種方式來(lái)確定一條導(dǎo)入語(yǔ)句能否被移除,如檢查對(duì)導(dǎo)入的使用,以及其在導(dǎo)出文件中是如何聲明的。

為了簡(jiǎn)化類型導(dǎo)入的判斷工作,TypeScript 此前引入了 import type 語(yǔ)法來(lái)聲明僅類型導(dǎo)入,或成員級(jí)別的僅類型導(dǎo)入:

import type * as UserTypes from "./user";

import { type UserModel, UserMiddleware } from "./user";

對(duì)應(yīng)的,還有一系列配置來(lái)進(jìn)一步細(xì)粒度地控制行為,如 --importsNotUsedAsValues? 用于確認(rèn)類型導(dǎo)入的使用(僅類型導(dǎo)入需要被顯式標(biāo)記,而未被使用的值導(dǎo)入仍然將會(huì)保留),--preserveValueImports 用于顯式避免部分導(dǎo)入語(yǔ)句的移除(所有值導(dǎo)入都將被完整保留,避免 TypeScript 無(wú)法檢測(cè)其使用方式的情況)等等。

而在 5.0 版本,TypeScript 引入了新的配置 --verbatimModuleSyntax 來(lái)進(jìn)一步簡(jiǎn)化這些情況,它的作用就簡(jiǎn)單多了:所有非僅類型導(dǎo)入/導(dǎo)出都會(huì)被保留,而僅類型導(dǎo)入/導(dǎo)出都會(huì)被移除。

moduleResolution 相關(guān)

這一部分包括了 --moduleResolution bundler? 與 Resolution Customization Flags 的相關(guān)介紹。

TypeScript 自 4.5 版本 來(lái)一直在持續(xù)改進(jìn) NodeJs 中的 ESM 支持,先后在 4.5 beta 與 4.7 正式中引入了 .mts、.cts? 擴(kuò)展名,支持了 package.json? 中的 exports, imports, type 等字段,以及新的 compilerOption.module? 與 compilerOptions.moduleResolution? 值:node16? 與 nodenext,這些能力很好地改進(jìn)了 TS + NodeJs + Pure ESM 的研發(fā)體驗(yàn),但實(shí)際上,前端er 們并不會(huì)僅僅使用 tsc 來(lái)進(jìn)行編譯,而其他的編譯工具其實(shí)并沒(méi)有這么多彎彎繞繞。

舉例來(lái)說(shuō),NodeJs 中的 ESM 強(qiáng)制要求你的相對(duì)導(dǎo)入路徑攜帶擴(kuò)展名,即 import ns from "./mod.mjs"?(你也可以使用 --experimental-specifier-resolution=node 配置來(lái)啟用自動(dòng)地路徑解析),這主要是為了貼合 NodeJs 在服務(wù)器環(huán)境下的性能表現(xiàn)。然而大部分的構(gòu)建工具其實(shí)不要求你這么做,它會(huì)融合 ESM 與 CJS 的模塊解析策略。

在 5.0 beta 版本,TS 引入了新的 moduleResolutio: bundler 配置,它會(huì)使用 NodeJs 的模塊解析策略,支持 ESM 語(yǔ)法,但不會(huì)強(qiáng)制你使用 ESM 的這些嚴(yán)格解析規(guī)則。同時(shí) 5.0 還引入了一系列細(xì)粒度的配置項(xiàng)來(lái)便于各個(gè)運(yùn)行時(shí)與構(gòu)建工具按照自己的需求進(jìn)行調(diào)整:

  • --allowImportingTsExtensions?,此配置啟用后,在相對(duì)導(dǎo)入 TS 文件時(shí)就能夠攜帶上擴(kuò)展名(.ts, .mts, .tsx,不包括 .cts ,因?yàn)?ESM 才是一家人)。但需要注意的是需要同時(shí)啟用 --noEmit 或者 --emitDeclarationOnly,這是因?yàn)檫@些文件導(dǎo)入路徑還需要被構(gòu)建工具進(jìn)行處理后才能正常使用,運(yùn)行時(shí)本身是無(wú)法
  • --resolvePackageJsonExports,--resolvePackageJsonImports,這兩個(gè)配置將分別強(qiáng)制 TS 在讀取 來(lái)自 node_modules 中的導(dǎo)入時(shí)去解析 package.json 中的 exports 與 imports 字段。在 moduleResolution 被指定為 node16 / nodenext / bundler 時(shí)默認(rèn)啟用。
  • --allowArbitraryExtensions?,啟用此配置后,TS 在導(dǎo)入一個(gè)非 JS/JSX/TS/TSX 擴(kuò)展名的文件時(shí),也會(huì)自動(dòng)去查找其類型聲明。如導(dǎo)入 style.css 時(shí)將嘗試加載 style.d.css.ts 聲明文件:
/* style.css */
.app-container {}

.app-main-title {}
// style.d.css.ts
declare const css: {
appContainer: string;
appMainTitle: string;
};

export default css;

你可能會(huì)想,為什么是 .d.css.ts?,而不是 .css.d.ts? ? 這是因?yàn)?nbsp;file.d.ts? 通常被視為 file.js/jsx? 的聲明文件,也就是 .css 其實(shí)被視為了不完整的 JS 文件名,這實(shí)際上是錯(cuò)誤的行為。

這一配置主要是為了避免在支持這些導(dǎo)入的運(yùn)行時(shí)或者構(gòu)建工具中產(chǎn)生類型報(bào)錯(cuò)(此前我們通常通過(guò) declare module '*.css' 來(lái)實(shí)現(xiàn)),它對(duì)業(yè)務(wù)開(kāi)發(fā)確實(shí)有著明顯的意義,社區(qū)可能又要為此涌現(xiàn)出一批新活了。

  • --customConditions?,NodeJs 支持在 package.json 的 exports 中指定 import / require / node / default 等值來(lái)設(shè)定其在不同條件(環(huán)境)下的文件入口。而這一配置則是為了更靈活地指定條件,如你可以在 tsconfig.json 中這樣配置:
{
"compilerOptions": {
"target": "es2022",
"moduleResolution": "bundler",
"customConditions": ["only-for-linbudu"]
}
}

這樣若是你的 npm 包 exports 中指定了這一條件,則它會(huì)將其視為最高優(yōu)先級(jí):

{
"name": "@linbudu/pkg",
"exports": {
".": {
"only-for-linbudu": "./private.mjs",
"node": "./public.mjs",
"import": "./public.mjs",
}
}
}

其他

類型全量導(dǎo)出

現(xiàn)在,你可以使用 export type * from 'module'? 或者 export type * as namespace from 'module' 來(lái)導(dǎo)出類型了:

// models/user.model.ts
export class UserModel {}

// models/index.ts
export type * as models from './user.model.ts';

// app.ts
import { models } from './models';

// √ 僅作為類型使用
const userModel: UserModel = {};

// × 不能被作為值使用
const userModel = new models.UserModel();

JSDoc 中的 @satisfies 與 @overload

TypeScript 4.9 版本中引入了用于進(jìn)行安全 upcast 操作的 satisfies 操作符(參考 TypeScript 4.9 beta 發(fā)布:鴿置的 ES 裝飾器、satisfies 操作符、類型收窄增強(qiáng)、單文件級(jí)別配置等),而在 5.0 版本中,為了支持在 JavaScript 文件中使用 JSDoc 進(jìn)行類型檢查的使用方式,現(xiàn)在你可以使用 @satisfies 標(biāo)簽來(lái)檢查類型,但同時(shí)在上下文中保持使用從原先值推導(dǎo)出的類型(這也是 satisfies 和 類型斷言最大的差異):

// @ts-check

// 類型“{ name: string; }”不滿足預(yù)期類型“{ name: string; version: string; }”。
/**
* @satisfies {{name:string, version:string}}
*/
let pkg = {
name: "mustard-cli",
};

另外一個(gè)在本次被添加的 JSDoc 標(biāo)簽是 @overload,它用于顯式標(biāo)明每一個(gè)函數(shù)的重載簽名,從而配合類型檢查,如以下的例子:

// @ts-check

/**
* @param {string} value
* @return {void}
*/

/**
* @param {number} value
* @param {number} [maximumFractionDigits]
* @return {void}
*/

/**
* @param {string | number} value
* @param {number} [maximumFractionDigits]
*/
function printValue(value, maximumFractionDigits) {
}

printValue("hello!", 123)?  是一個(gè)錯(cuò)誤的重載調(diào)用,但卻沒(méi)有提示報(bào)錯(cuò)信息,但如果為重載簽名添加 @overload 標(biāo)簽,TS 就能夠依次檢查其是否有符合的重載調(diào)用:

// @ts-check

/**
* @overload
* @param {string} value
* @return {void}
*/

/**
* @overload
* @param {number} value
* @param {number} [maximumFractionDigits]
* @return {void}
*/

/**
* @param {string | number} value
* @param {number} [maximumFractionDigits]
*/
function printValue(value, maximumFractionDigits) { }

// 類型“string”的參數(shù)不能賦給類型“number”的參數(shù)。
printValue("hello!", 123); // error!

廢棄功能

為了更好地迎接未來(lái)的 ECMAScript 演進(jìn),TypeScript 5.0 引入了對(duì)語(yǔ)言能力或配置項(xiàng)的廢棄計(jì)劃,以 keyofStringsOnly 配置為例,在 5.0 版本開(kāi)始,啟用此配置將會(huì)獲得一條警告:

TS9998: Flag 'keyofStringsOnly' is deprecated and will stop functioning in TypeScript 5.5. Specify 'ignoreDeprecations: "5.0"' to silence this error

在下一階段(如 5.5 版本),你仍然可以指定 keyofStringsOnly ,它也不會(huì)拋出任何錯(cuò)誤,但實(shí)際上它已經(jīng)不再有作用。在最后一個(gè)階段(如 6.0 版本),指定此配置將會(huì)拋出一個(gè)錯(cuò)誤。

在第一階段,你可以通過(guò)設(shè)置 ignoreDeprecations: "5.0" 來(lái)關(guān)閉所有由于使用在 5.0 版本開(kāi)始廢棄的功能而產(chǎn)生的警告。

已經(jīng)確定在 5.0 版本將開(kāi)始逐步廢棄的配置項(xiàng)包括 charset,noImplicitUseStrict,keyofStringsOnly,noFallthroughCasesInSwitch? 等,以及 target: ES3?  與 module: umd/system/amd。

tsconfig.json 多繼承

TypeScript 5.0 支持了 tsconfig.json 的 extends 配置的數(shù)組類型,用于同時(shí)繼承一組已有的規(guī)則,這一能力使得你能夠?qū)⒆约旱墓蚕砼渲眠M(jìn)一步拆解,再依據(jù)實(shí)際情況進(jìn)行組合:

{
"extends": ["./tsconfig.modern.json", "./tsconfig.node.json", "./tsconfig.strict.json"]
}

以上這個(gè)配置集成了包含現(xiàn)代語(yǔ)言特性配置、包含 Node 應(yīng)用配置以及包含嚴(yán)格檢查的配置文件。

單文件級(jí)別配置

TypeScript 5.0 現(xiàn)在支持單文件級(jí)別的配置,如你只想為當(dāng)前文件啟用嚴(yán)格檢查,其他文件仍然使用全局配置,可以這么做:

// @ts-strict

// 參數(shù) input 隱式具有 any 類型
const handler = (input) => input + 1;

目前支持的規(guī)則:

  • strict
  • noImplicitAny
  • strictNullChecks
  • strictFunctionTypes
  • strictBindCallApply
  • strictPropertyInitialization
  • noImplicitThis
  • useUnknownInCatchVariables
  • alwaysStrict
  • noUnusedLocals
  • noUnusedParameters
  • exactOptionalPropertyTypes
  • noImplicitReturns
  • noFallthroughCasesInSwitch
  • noUncheckedIndexedAccess
  • noImplicitOverride
  • noPropertyAccessFromIndexSignature

其配置項(xiàng)也均為小駝峰轉(zhuǎn)中劃線,如 @ts-no-property-access-from-index-signature。

責(zé)任編輯:武曉燕 來(lái)源: 林不渡也不是不能渡
相關(guān)推薦

2023-03-17 07:05:41

TypeScriptJSDoc 功能

2024-02-26 00:00:00

TypeScript裝飾器decorators

2009-03-05 09:25:11

2022-09-26 09:02:54

TS 裝飾器TypeScript

2021-08-04 08:33:59

TypeScriptConst Readonly

2021-12-15 12:59:56

Go泛型版Beta1

2009-06-23 21:02:42

Linux

2021-10-17 13:10:56

函數(shù)TypeScript泛型

2023-08-07 16:07:42

2022-06-19 22:54:08

TypeScript泛型工具

2023-01-05 17:13:28

TypeScript泛型組件

2021-12-15 10:23:56

Go 1.18 Bet語(yǔ)言泛型

2011-05-05 09:17:41

Firefox 5.0

2009-08-18 09:32:21

Silverlight

2024-04-23 08:23:36

TypeScript泛型Generics

2024-09-29 08:35:34

TypeScript枚舉安全性

2024-11-05 09:11:09

TypeScript開(kāi)發(fā)者代碼

2012-04-19 09:50:53

Chrome 19Be新版發(fā)布

2022-06-14 09:01:06

TypeScript泛型

2022-05-10 09:12:16

TypeScript裝飾器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)