今天,微軟宣佈 TypeScript 4.0 正式版上線了!這一新版本深入改進了表現力、生產力和可伸縮性,是 TypeScript 語言的新一代版本。
今天,我們很高興地宣佈TypeScript 4.0正式版終於上線了!它是我們深入改進表現力、生產力和可伸縮性的結果,是TypeScript語言的新一代版本。
如果你還不熟悉TypeScript,這裏簡單介紹一下:它是一種在JavaScript之上通過添加靜態類型語法來構建的語言。它的基本理念是,記下值的類型以及它們的使用位置後,可以使用TypeScript對代碼進行類型檢查,並在運行代碼之前(甚至在保存文件之前)告訴你代碼錯誤的相關信息。然後,你可以使用TypeScript編譯器從代碼中剝離類型,併爲你提供可在任何地方運行的簡潔易讀的JavaScript代碼。除了類型檢查之外,TypeScript還使用靜態類型來支持強大的編輯器工具,例如自動完成、代碼導航、重構等。實際上,如果你在Visual Studio Code或Visual Studio這樣的編輯器中使用過JavaScript,那麼你已經用上了類型和TypeScript帶來的體驗。可以在我們的網站上了解更多相關信息。
TypeScript 4.0沒有引入特別重大的更改。實際上,如果你剛剛開始接觸這種語言,那麼現在是開始使用它的最佳時機。它的社區已經成熟完善,並在不斷髮展,擁有可運行的代碼和很棒的新資源可供學習。還有一件事情:儘管我們爲4.0引入了那麼多好東西,但你實際上只需要瞭解TypeScript的基礎知識就可以開始生產應用了!
如果你已經在項目中使用TypeScript,則可以通過NuGet獲取它,也可以通過以下命令使用npm獲取:
npm install -D typescript
你還可以通過以下方式獲得編輯器支持:
- 下載Visual Studio 2019/2017
- 安裝Visual Studio Code的內部版本,或按照以下說明使用新版本的TypeScript。
4.0之旅
TypeScript是當今許多人的JavaScript技術棧的核心部分。在npm上,TypeScript在7月首次實現了超過5000萬的月下載量!儘管我們知道它總有增長和改進的餘地,但很明顯,大多數使用TypeScript編碼的開發人員確實很喜歡它。StackOverflow的最新開發人員調查將TypeScript列爲第二受歡迎的語言。在最新的JS現狀調查中,使用TypeScript的開發人員中有大約89%表示會再次使用它。
值得一提的是我們走到今天所走過的旅程。在之前的兩個主要版本中,我們回顧了多年來閃耀的一些亮點。對於TypeScript 4.0,我們將保持這種傳統。
從3.0版本向前看,可以看到許多令人眼花繚亂的更改,但是TypeScript 3.0本身就產生了很大的衝擊。統一元組類型和參數列表是當時的一大亮點,可在函數上啓用大量已有的JavaScript模式。這個發行版還提供了項目參考,以幫助擴展、組織和共享代碼庫。3.0版的一個產生重大影響的小更改是對any引入了類型安全的替代方法,稱爲unknown。
TypeScript 3.1擴展了映射類型的功能以處理元組和數組類型,並極大簡化了將屬性附加到函數的過程,而無需使用TypeScript專屬的運行時功能(已停用)。
TypeScript 3.2允許對象在泛型類型上傳播,並通過嚴格類型化bind、call和apply,利用3.0的功能更好地建模函數的元編程。TypeScript 3.3更多關注穩定性,但也改進了聯合類型方法,並在–build模式下添加了文件增量式構建。
在3.4版本中,我們進一步支持函數式模式,更好地支持不可變數據結構,並改進了對高階泛型函數的推斷。這個發行版的一大改進是引入了–incremental標誌,該方法避免了在每次TypeScript運行時完全重建,從而加快了編譯和類型檢查的速度。
在TypeScript 3.5和3.6中加強了一些類型系統規則,還帶來了更智能的兼容性檢查規則。
TypeScript 3.7是一個非常值得關注的版本,因爲它很好地結合了許多新的類型系統特性與ECMAScript特性。在類型系統方面,我們加入了遞歸類型別名引用和對斷言樣式函數的支持,這兩者都是獨特的類型系統特性。從JavaScript方面來看,該版本帶來了可選鏈和空值合併功能,這是TypeScript和JavaScript用戶最期待的兩項功能。
最近,3.8和3.9帶來了僅類型的導入/導出,以及許多ECMAScript特性,例如私有字段、模塊中的頂級await和新的export*語法。這些版本還帶來了性能和可伸縮性優化。
我們還沒有提到關於語言服務、基礎架構、網站和其他核心項目中的那些工作,這些工作對於TypeScript的體驗非常關鍵。核心團隊的項目之外,我們在生態系統中還有非常出色的貢獻者社區,他們推動了體驗的不斷改進,並通過DefinitelyTyped甚至TypeScript本身提供了幫助。在2012年剛開始時,DefinitelyTyped僅有80個拉取請求。在2019年,它有超過8300個拉取請求,非常震撼人心。這些貢獻是TypeScript體驗的基礎,這樣一個繁忙而熱情的社區在不斷改善我們的生態系統,並推動我們不斷改進,我們對此表示感謝。
新內容
-
可變元組類型
-
標記的元組元素
-
構造器的類屬性推斷
-
短路賦值運算符
-
catch子句綁定unknown
-
定製JSX工廠
-
加快了帶有–noEmitOnError的build模式的速度
-
帶有–noEmit的–incremental
-
編輯器改進
- 轉換爲可選鏈
/** @depreacted */
支持- 啓動時的部分編輯模式
- 更智能的自動導入
-
我們的新網站!
-
重大更改
可變元組類型
考慮JavaScript中稱爲concat的函數,該函數接收兩個數組或元組類型,並將它們連接在一起以創建一個新數組。
function concat(arr1, arr2) {
return [...arr1, ...arr2];
}
考慮tail,它接收一個數組或元組,並返回除第一個元素外的所有元素。
function tail(arg) {
const [_, ...result] = arg;
return result
}
我們如何在TypeScript中爲它們類型化?
對於concat,我們在較舊版本的TS中唯一可以做的就是嘗試編寫一些重載。
function concat<>(arr1: [], arr2: []): [A];
function concat<A>(arr1: [A], arr2: []): [A];
function concat<A, B>(arr1: [A, B], arr2: []): [A, B];
function concat<A, B, C>(arr1: [A, B, C], arr2: []): [A, B, C];
function concat<A, B, C, D>(arr1: [A, B, C, D], arr2: []): [A, B, C, D];
function concat<A, B, C, D, E>(arr1: [A, B, C, D, E], arr2: []): [A, B, C, D, E];
function concat<A, B, C, D, E, F>(arr1: [A, B, C, D, E, F], arr2: []): [A, B, C, D, E, F];)
第二個數組始終爲空時會冒出來七個重載。當arr2有一個參數時我們再加一些看看。
function concat<A2>(arr1: [], arr2: [A2]): [A2];
function concat<A1, A2>(arr1: [A1], arr2: [A2]): [A1, A2];
function concat<A1, B1, A2>(arr1: [A1, B1], arr2: [A2]): [A1, B1, A2];
function concat<A1, B1, C1, A2>(arr1: [A1, B1, C1], arr2: [A2]): [A1, B1, C1, A2];
function concat<A1, B1, C1, D1, A2>(arr1: [A1, B1, C1, D1], arr2: [A2]): [A1, B1, C1, D1, A2];
function concat<A1, B1, C1, D1, E1, A2>(arr1: [A1, B1, C1, D1, E1], arr2: [A2]): [A1, B1, C1, D1, E1, A2];
function concat<A1, B1, C1, D1, E1, F1, A2>(arr1: [A1, B1, C1, D1, E1, F1], arr2: [A2]): [A1, B1, C1, D1, E1, F1, A2];
很明顯這變得越來越離譜了。不幸的是,在類型化tail之類的函數時,你也會遇到同樣的問題。
下面是另一種情況,我們稱之爲“被一千個重載搞垮”,它甚至什麼問題都解決不了。它只爲我們想寫的重載提供正確的類型(不管重載有多少)。如果我們想做一個通行模式,就需要下面這種重載:
function concat<T, U>(arr1: T[], arr2, U[]): Array<T | U>;
但在使用元組時,這個簽名不會包含輸入長度或元素順序的任何信息。
TypeScript 4.0帶來了兩個基礎更改,並在推斷方面進行了改進,從而可以類型化這些內容。
第一個更改是元組類型語法中的spread現在可以泛型。這意味着即使我們不知道要操作的實際類型,也可以表示對元組和數組的高階操作。在這些元組類型中實例化泛型spread(或用真實類型替換)時,它們可以產生其他數組和元組類型集。
例如,我們可以類型化tail那樣的函數,而不會出現“被一千個重載搞垮”的問題。
function tail<T extends any[]>(arr: readonly [any, ...T]) {
const [_ignored, ...rest] = arr;
return rest;
}
const myTuple = [1, 2, 3, 4] as const;
const myArray = ["hello", "world"];
// type [2, 3, 4]
const r1 = tail(myTuple);
// type [2, 3, ...string[]]
const r2 = tail([...myTuple, ...myArray] as const);
第二個更改是,rest元素可以出現在元組中的任何位置,而不僅僅是在結尾!
type Strings = [string, string];
type Numbers = [number, number];
// [string, string, number, number]
type StrStrNumNum = [...Strings, ...Numbers];
以前,TypeScript會發出如下錯誤。
A rest element must be last in a tuple type.
但是現在這種限制取消了。
當我們在沒有已知長度的類型中spread時,結果類型也將變得不受限制,並且後面的所有元素都會變爲結果的rest元素類型。
type Strings = [string, string];
type Numbers = number[]
// [string, string, ...Array<number | boolean>]
type Unbounded = [...Strings, ...Numbers, boolean];
將這兩種行爲結合在一起,我們可以爲concat編寫一個類型良好的簽名:
type Arr = readonly any[];
function concat<T extends Arr, U extends Arr>(arr1: T, arr2: U): [...T, ...U] {
return [...arr1, ...arr2];
}
儘管一個簽名仍然有些冗長,但它畢竟只有一個,只需寫一次,並且在所有數組和元組上都具有可預測的行爲。
這個功能很棒,在其他更復雜的場景中更有用。例如,考慮一個函數來部分應用參數,名爲partialCall。partialCall接收一個函數(這裏就叫f)以及該函數期望的幾個初始參數。然後,它返回一個新函數,接收它需要的其他所有參數,收到後調用f。
function partialCall(f, ...headArgs) {
return (...tailArgs) => f(...headArgs, ...tailArgs)
}
TypeScript 4.0改進了rest參數和rest元組元素的推斷過程,因此我們可以類型化它並使其“正常工作”。
type Arr = readonly unknown[];
function partialCall<T extends Arr, U extends Arr, R>(f: (...args: [...T, ...U]) => R, ...headArgs: T) {
return (...b: U) => f(...headArgs, ...b)
}
在這種情況下,partialCall會知道其最初可以使用和不能使用哪些參數,並返回一個可以正確接收和拒絕剩餘內容的函數。
const foo = (x: string, y: number, z: boolean) => {}
// This doesn't work because we're feeding in the wrong type for 'x'.
const f1 = partialCall(foo, 100);
// ~~~
// error! Argument of type 'number' is not assignable to parameter of type 'string'.
// This doesn't work because we're passing in too many arguments.
const f2 = partialCall(foo, "hello", 100, true, "oops")
// ~~~~~~
// error! Expected 4 arguments, but got 5.
// This works! It has the type '(y: number, z: boolean) => void'
const f3 = partialCall(foo, "hello");
// What can we do with f3 now?
f3(123, true); // works!
f3();
// error! Expected 2 arguments, but got 0.
f3(123, "hello");
// ~~~~~~~
// error! Argument of type '"hello"' is not assignable to parameter of type 'boolean'.
可變元組類型創造了許多新模式,尤其是在函數組合方面。我們希望利用它來改善對JavaScript內置的bind方法的類型檢查。此外還有其他一些推斷改進和模式,想了解更多信息,可以查看可變元組的拉取請求。
標記的元組元素
改善元組類型和參數列表的體驗很重要,因爲它使我們能夠圍繞常見的JavaScript習慣用法進行強類型驗證——實際上只是對參數列表進行切片和切塊,並將它們傳遞給其他函數。對rest參數使用元組類型是其中的關鍵。
例如,以下函數使用元組類型作爲rest參數:
function foo(...args: [string, number]): void {
// ...
}
……應該與以下函數沒有區別……
function foo(arg0: string, arg1: number): void {
// ...
}
……對於foo的任何調用者。
foo("hello", 42); // works
foo("hello", 42, true); // error
foo("hello"); // error
不過可讀性就有區別了。在第一個示例中,我們沒有第一個和第二個元素的參數名稱。儘管這些對類型檢查沒有影響,但元組位置上缺少標記會難以傳達我們的意圖。
因此,在TypeScript 4.0中,元組類型現在可以提供標記。
type Range = [start: number, end: number];
爲了進一步加強參數列表和元組類型之間的聯繫,我們讓rest元素和可選元素的語法與參數列表的語法一致。
type Foo = [first: number, second?: string, ...rest: any[]];
標記元組使用時有些規則,其中一條是:在標記一個元組元素時,還必須標記元組中的所有其他元素。
type Bar = [first: string, number];
// ~~~~~~
// error! Tuple members must all have names or all not have names.
值得注意的是,在解構時標記不需要我們用不同的名稱命名變量。它們純粹是爲文檔和工具鏈服務的。
function foo(x: [first: string, second: number]) {
// ...
// note: we didn't need to name these 'first' and 'second'
let [a, b] = x;
// ...
}
總的來說,當利用圍繞元組和參數列表的模式,並以類型安全的方式實現重載時,帶標記的元組非常方便好用。實際上,TypeScript的編輯器支持會在可能的情況下將它們顯示爲重載。
瞭解更多信息,請查看帶標記的元組元素的拉取請求。
構造器的類屬性推斷
當啓用noImplicitAny時,TypeScript 4.0現在可以使用控制流分析來確定類中屬性的類型。
class Square {
// Previously: implicit any!
// Now: inferred to `number`!
area;
sideLength;
constructor(sideLength: number) {
this.sideLength = sideLength;
this.area = sideLength ** 2;
}
}
如果構造器的路徑並非都分配給一個實例成員,則該屬性可能被認爲是undefined的。
class Square {
sideLength;
constructor(sideLength: number) {
if (Math.random()) {
this.sideLength = sideLength;
}
}
get area() {
return this.sideLength ** 2;
// ~~~~~~~~~~~~~~~
// error! Object is possibly 'undefined'.
}
}
如果你更瞭解某些情況(例如,你擁有某種initialize方法),則當你處於strictPropertyInitialization中時,需要使用顯式類型註釋以及明確的賦值斷言(!)。
class Square {
// definite assignment assertion
// v
sideLength!: number;
// ^^^^^^^^
// type annotation
constructor(sideLength: number) {
this.initialize(sideLength)
}
initialize(sideLength: number) {
this.sideLength = sideLength;
}
get area() {
return this.sideLength ** 2;
}
}
更多信息請見拉取請求。
短路賦值運算符
JavaScript和許多語言都支持一組稱爲"複合賦值運算符"的運算符。複合賦值運算符將一個運算符應用於兩個參數,然後將結果賦給左側。你可能以前看過這些:
// Addition
// a = a + b
a += b;
// Subtraction
// a = a - b
a -= b;
// Multiplication
// a = a * b
a *= b;
// Division
// a = a / b
a /= b;
// Exponentiation
// a = a ** b
a **= b;
// Left Bit Shift
// a = a << b
a <<= b;
JavaScript中有很多運算符都有對應的賦值運算符!但是有三個值得注意的例外:邏輯和(&&),邏輯或(||)和空值合併(??)。
所以TypeScript 4.0支持了一個新的ECMAScript特性,添加了三個新的賦值運算符:&&=,||=和??=。
這些運算符非常適合替換下面這種代碼示例:
a = a && b;
a = a || b;
a = a ?? b;
或者像下面這樣的if代碼段:
// could be 'a ||= b'
if (!a) {
a = b;
}
我們甚至看到了一些模式,可以在需要時懶惰地初始化值。
let values: string[];
// Before
(values ?? (values = [])).push("hello");
// After
(values ??= []).push("hello");
在極少數情況下,你使用帶有副作用的getter或setter時,需要注意的是這些運算符僅在必要時執行賦值。從這個意義上講,"短路"的不僅是運算符的右側,賦值本身也短路了。
obj.prop ||= foo();
// roughly equivalent to either of the following
obj.prop || (obj.prop = foo());
if (!obj.prop) {
obj.prop = foo();
}
可以試着運行 這個示例,看看它和總是執行賦值有什麼區別。
const obj = {
get prop() {
console.log("getter has run");
// Replace me!
return Math.random() < 0.5;
},
set prop(_val: boolean) {
console.log("setter has run");
}
};
function foo() {
console.log("right side evaluated");
return true;
}
console.log("This one always runs the setter");
obj.prop = obj.prop || foo();
console.log("This one *sometimes* runs the setter");
obj.prop ||= foo();
有關更多細節可以查看拉取請求。你也可以查看TC39的提案存儲庫。
catch子句綁定支持unknown
自TypeScript誕生以來,catch子句變量始終按any類型化。這意味着TypeScript允許你對它們進行任何操作。
try {
// ...
}
catch (x) {
// x has type 'any' - have fun!
console.log(x.message);
console.log(x.toUpperCase());
x++;
x.yadda.yadda.yadda();
}
上述代碼會有一些無法預期的行爲!由於這些變量默認情況下的類型爲any,因此它們沒有任何類型安全性可以防止無效操作。
因此,TypeScript 4.0現在允許你將catch子句變量的類型指定爲unknown。unknown比any更安全,因爲它會在我們操作值之前提醒我們執行某種類型檢查。
try {
// ...
}
catch (e: unknown) {
// error!
// Property 'toUpperCase' does not exist on type 'unknown'.
console.log(e.toUpperCase());
if (typeof e === "string") {
// works!
// We've narrowed 'e' down to the type 'string'.
console.log(e.toUpperCase());
}
}
儘管默認情況下catch變量的類型不會更改,但我們將來可能會考慮使用新的–strict模式標誌,以便用戶選擇啓用此行爲。同時,應該可以編寫一個lint規則來強制catch變量具有如下顯式註解之一:: any或: unknown。
有關更多信息,可以查看拉取請求。
定製JSX工廠
使用JSX時,fragment是JSX元素的一種,允許我們返回多個子元素。當我們第一次在TypeScript中實現fragment時,我們對其他庫如何利用它們並不瞭解。如今,大多數鼓勵使用JSX和支持fragment的庫都具有類似的API設計。
在TypeScript 4.0中,用戶可以通過新的jsxFragmentFactory選項來自定義fragment工廠。
例如,以下tsconfig.json文件告訴TypeScript以與React兼容的方式轉換JSX,但將每個工廠調用(invocation)切換爲h而不是React.createElement,並使用Fragment而不是React.Fragment。
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"jsx": "react",
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment"
}
}
如果需要基於各個文件使用不同的JSX工廠,則可以利用新的/** @jsxFrag */註釋。例如,下面的內容:
// Note: these pragma comments need to be written
// with a JSDoc-style multiline syntax to take effect.
/** @jsx h */
/** @jsxFrag Fragment */
import { h, Fragment } from "preact";
let stuff = <>
<div>Hello</div>
</>;
將輸出成這樣的JavaScript:
// Note: these pragma comments need to be written
// with a JSDoc-style multiline syntax to take effect.
/** @jsx h */
/** @jsxFrag Fragment */
import { h, Fragment } from "preact";
let stuff = h(Fragment, null,
h("div", null, "Hello"));
查看拉取請求以獲取更多信息!
加快了帶有–noEmitOnError的build模式的速度
以前,使用–noEmitOnError標誌時,當先前的編譯在–incremental下出現錯誤,編譯速度將非常緩慢。這是因爲基於–noEmitOnError標誌,上次編譯的任何信息都不會緩存在.tsbuildinfo文件中。
TypeScript 4.0對此進行了更改,從而在這些情況下極大地提高了速度,進而改進了–build模式的場景(這意味着同時有–incremental和–noEmitOnError)。
有關詳細信息,請查看拉取請求。
帶有–noEmit的–incremental
TypeScript 4.0允許我們在利用–incremental編譯時使用–noEmit標誌。以前不允許這樣做,因爲–incremental需要發出.tsbuildinfo文件。
有關詳細信息,請查看拉取請求。
編輯器改進
TypeScript編譯器不僅可以爲大多數主流編輯器提供較好的TS編輯體驗,還可以改進Visual Studio系列編輯器的JavaScript開發體驗。
根據你使用的編輯器,在編輯器中使用新的TypeScript/JavaScript功能時會有區別:
- Visual Studio Code支持選擇不同版本的TypeScript。另外,還有JavaScript/TypeScript Nightly Extension來緊跟最新版本(通常非常穩定)。
- Visual Studio 2017/2019有上面的SDK安裝程序和MSBuild安裝。
更多信息見TS編輯器支持列表。
轉換爲可選鏈
可選鏈是一項新功能,受到了廣泛的歡迎。TypeScript 4.0在轉換常見模式時可以利用可選鏈和空值合併的優勢!
我們認爲這種重構應該能捕獲大多數用例的意圖,尤其是當TypeScript對你的類型有更精確的瞭解時。
有關詳細信息,請查看拉取請求。
/** @deprecated */
支持
現在,TypeScript的編輯支持可以識別聲明中是否帶有/** @deprecated*/
JSDoc註釋。該信息顯示在自動完成列表中,並作爲編輯器可以特別處理的建議診斷。在像VSCode這樣的編輯器中,deprecated的值通常顯示爲刪除線樣式。
有關詳細信息,查看拉取請求。
啓動時的部分編輯模式
很多用戶抱怨啓動時間緩慢,尤其是在大型項目中。具體來說,罪魁禍首通常是一個稱爲項目加載的過程,該過程與我們編譯器的程序構建步驟大致相同。這一過程從一組初始文件開始,解析它們、解析它們的依賴、再解析那些依賴,解析那些依賴的依賴,等等,最後需要花費很長時間。項目越大,啓動延遲可能會越長。
所以我們一直在努力爲開發人員提供一種新的模式,在獲得完整的語言服務體驗之前提供部分體驗。這裏的核心思想是,編輯者可以運行僅具有單個文件視圖的輕量級部分服務器。
這種新模式可以將TypeScript在代碼庫上開始交互之前的準備時間從20秒到1分鐘縮短到只有幾秒鐘。比如說,在較大的代碼庫上重啓編輯器時,TS 3.9版沒法立即提供自動完成和快速信息;另一方面,TS 4.0可以立即提供完整的編輯體驗,同時在後臺加載整個項目。
當前,唯一支持此模式的編輯器是Visual Studio Code,但UX和功能仍有改進的餘地。我們列出了準備加入的改進,希望獲得更多反饋。
有關更多信息,你可以查看原始提案,拉取請求,以及後續的meta問題。
更智能的自動導入
自動導入是一個了不起的功能。但是,自動導入在用TypeScript編寫的包上不起作用——也就是說,我們得在項目的其他位置至少寫了一個顯式導入。
爲什麼自動導入適用於@types軟件包,而不適用於使用自己類型的包呢?其實自動導入是通過檢查項目中已經包含的軟件包來實現的。TypeScript有一個怪癖,可以自動包括node_modules/@types中的所有包,而忽略其他包;但爬取所有node_modules包的開銷可能會很昂貴。
當你嘗試自動導入剛剛安裝但尚未使用的內容時,這些都會導致糟糕的體驗。
TypeScript 4.0現在可以包含你在package.json的dependencies(和peerDependencies)字段中列出的包。這些包中的信息僅用於改進自動導入,不會更改類型檢查等其他內容。這樣就避免了遍歷node_modules目錄的成本,使我們可以爲所有帶類型的依賴項提供自動導入。
當你的package.json列出了超過十項尚未導入的類型化依賴項時,這個功能會自動禁用,以避免緩慢的項目加載過程。要強制開啓它或完全禁用它,你可以配置編輯器。在Visual Studio Code中是"Include Package JSON Auto Imports"設置(或typescript.preferences.includePackageJsonAutoImports)。
我們的新網站!
TypeScript網站最近被徹底重寫了!
詳細信息可以參考之前的文章:
重大更改
lib.d.ts
我們的lib.d.ts聲明已更改,具體來說是DOM的類型已更改。主要是刪除了document.origin,它僅在IE的舊版本中有效,而Safari MDN建議改用self.origin。
屬性重寫訪問器(反之亦然)是錯誤
以前,只有在使用useDefineForClassFields時,屬性重寫訪問器或訪問器重寫屬性是一個錯誤;但現在,在派生類中聲明一個將重寫基類中的getter或setter的屬性時總是發出錯誤。
class Base {
get foo() {
return 100;
}
set foo() {
// ...
}
}
class Derived extends Base {
foo = 10;
// ~~~
// error!
// 'foo' is defined as an accessor in class 'Base',
// but is overridden here in 'Derived' as an instance property.
}
class Base {
prop = 10;
}
class Derived extends Base {
get prop() {
// ~~~~
// error!
// 'prop' is defined as a property in class 'Base', but is overridden here in 'Derived' as an accessor.
return 100;
}
}
有關詳細信息,查看拉取請求。
delete的操作數必須是可選的。
在strictNullChecks中使用delete運算符時,操作數現在必須爲any、unknown、never或爲可選(因爲它在類型中包含undefined)。否則,使用delete運算符是錯誤的。
interface Thing {
prop: string;
}
function f(x: Thing) {
delete x.prop;
// ~~~~~~
// error! The operand of a 'delete' operator must be optional.
}
關於更多信息,查看拉取請求。
TypeScript的Node工廠用法已棄用
如今,TypeScript提供了一組用於生成AST節點的“工廠”函數。但是,TypeScript 4.0提供了新的node工廠API。因此TypeScript 4.0決定棄用使用這些舊函數,推薦改用新函數。
有關更多信息,請查看拉取請求。
下一步計劃
TypeScript 4.1的迭代計劃已經上線了,你可以大致瞭解一下。同時,你可以在工作區或編輯器中使用nightly構建來預覽4.1中添加的新特性。無論你是在使用TypeScript 4.0還是下一版本,我們都希望聽到你的反饋!可以通過Twitter聯繫我們,或在GitHub上發起問題。
我們再一次爲社區所做的一切工作和奉獻精神深表感謝。我們希望讓TypeScript和JavaScript的編碼體驗成爲你應得的純粹樂趣。爲此,我們需要改善語言和編輯體驗、提升性能、迭代我們的用戶體驗、降低入門和學習的門檻等等。
非常感謝大家,請享用4.0版本吧,編程愉快!
原文鏈接:
https://devblogs.microsoft.com/typescript/announcing-typescript-4-0/