在 TypeScript 3.1 中,元組和數(shù)組上的映射對(duì)象類(lèi)型現(xiàn)在產(chǎn)生新的元組/數(shù)組,而不是創(chuàng)建一個(gè)新的類(lèi)型,其中的成員,比如push()
,pop()
和length
將被轉(zhuǎn)換。例如:
type MapToPromise<T> = { [K in keyof T]: Promise<T[K]> };
type Coordinate = [number, number]
type PromiseCoordinate = MapToPromise<Coordinate>; // [Promise<number>, Promise<number>]
MapToPromise
使用一種類(lèi)型T
,當(dāng)該類(lèi)型是一個(gè)元組,例如Coordinate
,它只轉(zhuǎn)換數(shù)字屬性。在[number, number]
中,有兩個(gè)數(shù)字命名的屬性:0
和1
。當(dāng)給出這樣的元組時(shí),MapToPromise
將創(chuàng)建一個(gè)新的元組,其中0
和1
屬性是原始類(lèi)型的Promise
s。因此,結(jié)果類(lèi)型PromiseCoordinate
最終會(huì)得到類(lèi)型[Promise<number>, Promise<number>]
。
TypeScript 3.1 能夠在函數(shù)聲明和const
-declared functons 上定義屬性,只需在同一范圍內(nèi)分配這些函數(shù)的屬性即可。這允許我們編寫(xiě)規(guī)范的JavaScript代碼而不求助于namespace
。例如:
function readImage(path: string, callback: (err: any, image: Image) => void) {
// ...
}
readImage.sync = (path: string) => {
const contents = fs.readFileSync(path);
return decodeImageSync(contents);
}
在這里,我們有一個(gè)以非阻塞異步方式讀取圖像的readImage
函數(shù)。除了readImage
外,我們?cè)?code>readImage提供了一個(gè)方便的函數(shù),名為readImage.sync
。
雖然ECMAScript導(dǎo)出通常是提供此功能的更好方式,但這種新的支持允許使用此樣式編寫(xiě)的代碼“僅僅工作” TypeScript。另外,這種屬性聲明方法讓我們?cè)赗eact無(wú)狀態(tài)功能組件(SFCs)上表達(dá)常用模式,例如defaultProps
和propTypes
。
export const FooComponent => ({ name }) => (
<div>Hello! I am {name}</div>
);
FooComponent.defaultProps = {
name: "(anonymous)",
};
更具體地說(shuō),同態(tài)映射類(lèi)型類(lèi)似于上面的形式。
來(lái)自社區(qū)的反饋以及相關(guān)的經(jīng)驗(yàn)告訴我們,利用最新的TypeScript功能同時(shí)也容納舊版本的用戶(hù)是很困難的。TypeScript引入了一項(xiàng)名為typesVersions
的新功能,以幫助滿(mǎn)足這些方案。
在 TypeScript 3.1 中使用節(jié)點(diǎn)模塊分辨率時(shí),當(dāng) TypeScript 破解打開(kāi)package.json
文件以確定需要讀取哪些文件時(shí),它首先會(huì)查看名為typesVersions
的新字段。帶有typesVersions
字段的package.json
可能如下所示:
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
">=3.1": { "*": ["ts3.1/*"] }
}
}
這package.json
告訴TypeScript檢查當(dāng)前版本的TypeScript是否正在運(yùn)行。如果它是3.1或更高版本,它會(huì)計(jì)算出您相對(duì)于包導(dǎo)入的路徑,并從包的ts3.1
文件夾中讀取。這就是{ "*": ["ts3.1/*"] }
表達(dá)的意思 - 如果你現(xiàn)在熟悉路徑映射,它的工作原理就是這樣的。
因此,在上面的示例中,如果我們從"package-name"
中導(dǎo)入,在TypeScript 3.1中運(yùn)行時(shí),我們將嘗試從[...]/node_modules/package-name/ts3.1/index.d.ts
(和其他相關(guān)路徑)解析。如果我們從package-name/foo
導(dǎo)入,我們將嘗試尋找[...]/node_modules/package-name/ts3.1/foo.d.ts
和[...]/node_modules/package-name/ts3.1/foo/index.d.ts
。
如果我們?cè)谶@個(gè)例子中沒(méi)有在 TypeScript 3.1 中運(yùn)行怎么辦?好吧,如果typesVersions
中沒(méi)有匹配的字段,TypeScript會(huì)回退到types
字段,因此 TypeScript 3.0 及更早版本將被重定向到[...]/node_modules/package-name/index.d.ts
。
TypeScript決定編譯器和語(yǔ)言版本是否匹配的方式是使用Node的semver范圍。
typesVersions
可以支持多個(gè)字段,其中每個(gè)字段名稱(chēng)由要匹配的范圍指定。
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
">=3.2": { "*": ["ts3.2/*"] },
">=3.1": { "*": ["ts3.1/*"] }
}
}
由于范圍可能會(huì)重疊,因此確定應(yīng)用哪種重定向是特定于訂單的。這意味著在上面的示例中,即使>=3.2
和>=3.1
匹配器都支持 TypeScript 3.2 及更高版本,反轉(zhuǎn)順序也可能有不同的行為,因此上述示例將不等同于以下示例:
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
// NOTE: this doesn't work!
">=3.1": { "*": ["ts3.1/*"] },
">=3.2": { "*": ["ts3.2/*"] }
}
}
更多建議: