TypeScript 2.6
严格的函数类型
TypeScript 2.6 引入了一个新的严格检查标志,strictFunctionTypes。 strictFunctionTypes 开关是 strict 系列开关的一部分,这意味着它在 strict 模式下默认为开启状态。 你可以通过在命令行或 tsconfig.json 中设置 --strictFunctionTypes false 来选择退出。
在 strictFunctionTypes 下,函数类型参数位置是逆变检查而不是双变检查。 有关方差对函数类型意味着什么的一些背景知识,请查看什么是协变和逆变?。
更严格的检查适用于所有函数类型,除了那些源自方法或构造函数声明的函数类型。 特意排除方法是为了确保泛型类和接口(例如 Array<T>)继续主要保持协变关系。
考虑以下示例,其中 Animal 是 Dog 和 Cat 的超类型:
declare let f1: (x: Animal) => void;
declare let f2: (x: Dog) => void;
declare let f3: (x: Cat) => void;
f1 = f2; // 在 --strictFunctionTypes 下错误
f2 = f1; // 可以
f2 = f3; // 错误第一个赋值在默认类型检查模式下是允许的,但在严格函数类型模式下会被标记为错误。 直观地说,默认模式允许赋值是因为它可能是合理的,而严格函数类型模式使其成为错误,因为它不是可证明合理的。 无论哪种模式,第三个赋值都是错误,因为它永远不合理。
描述这个例子的另一种方式是,在默认类型检查模式下,类型 (x: T) => void 对于 T 是双变的(即协变或逆变),但在严格函数类型模式下对于 T 是逆变的。
示例
interface Comparer<T> {
compare: (a: T, b: T) => number;
}
declare let animalComparer: Comparer<Animal>;
declare let dogComparer: Comparer<Dog>;
animalComparer = dogComparer; // 错误
dogComparer = animalComparer; // 可以第一个赋值现在是一个错误。实际上,T 在 Comparer<T> 中是逆变的,因为它仅用于函数类型参数位置。
顺便说一下,请注意,尽管某些语言(例如 C# 和 Scala)需要方差注释(out/in 或 +/-),但由于 TypeScript 的结构类型系统,方差是从泛型类型中类型参数的实际使用中自然产生的。
注意
在 strictFunctionTypes 下,如果 compare 被声明为方法,则第一个赋值仍然允许。 实际上,T 在 Comparer<T> 中是双变的,因为它仅用于方法参数位置。
interface Comparer<T> {
compare(a: T, b: T): number;
}
declare let animalComparer: Comparer<Animal>;
declare let dogComparer: Comparer<Dog>;
animalComparer = dogComparer; // 由于双变性,允许
dogComparer = animalComparer; // 允许TypeScript 2.6 还改进了涉及逆变位置的类型推断:
function combine<T>(...funcs: ((x: T) => void)[]): (x: T) => void {
return x => {
for (const f of funcs) f(x);
};
}
function animalFunc(x: Animal) {}
function dogFunc(x: Dog) {}
let combined = combine(animalFunc, dogFunc); // (x: Dog) => void上面,对 T 的所有推断都来自逆变位置,因此我们推断出 T 的最佳公共子类型。 这与来自协变位置的推断形成对比,在协变位置我们推断出最佳公共超类型。
在模块中缓存标记模板对象
TypeScript 2.6 修复了标记模板字符串的输出,使其更好地符合 ECMAScript 规范。 根据 ECMAScript 规范,每次评估模板标签时,应该传递相同的模板字符串对象(相同的 TemplateStringsArray)作为第一个参数。 在 TypeScript 2.6 之前,生成的输出每次都是一个全新的模板对象。 虽然字符串内容相同,但这种输出会影响使用字符串标识进行缓存失效的库,例如 lit-html。
示例
export function id(x: TemplateStringsArray) {
return x;
}
export function templateObjectFactory() {
return id`hello world`;
}
let result = templateObjectFactory() === templateObjectFactory(); // TS 2.6 中为 true结果生成以下代码:
"use strict";
var __makeTemplateObject =
(this && this.__makeTemplateObject) ||
function(cooked, raw) {
if (Object.defineProperty) {
Object.defineProperty(cooked, "raw", { value: raw });
} else {
cooked.raw = raw;
}
return cooked;
};
function id(x) {
return x;
}
var _a;
function templateObjectFactory() {
return id(
_a || (_a = __makeTemplateObject(["hello world"], ["hello world"]))
);
}
var result = templateObjectFactory() === templateObjectFactory();注意:此更改引入了一个新的输出辅助函数
__makeTemplateObject; 如果你在tslib中使用importHelpers,则需要更新到 1.8 或更高版本。
命令行上的本地化诊断信息
TypeScript 2.6 npm 包附带了 13 种语言的诊断消息本地化版本。 在命令行上使用 --locale 标志时,可以使用本地化消息。
示例
俄语的错误消息:
c:\ts>tsc --v
Version 2.6.0-dev.20171003
c:\ts>tsc --locale ru --pretty c:\test\a.ts
../test/a.ts(1,5): error TS2322: Тип ""string"" не может быть назначен для типа "number".
1 var x: number = "string";
~日语的帮助信息:
PS C:\ts> tsc --v
Version 2.6.0-dev.20171003
PS C:\ts> tsc --locale ja-jp
バージョン 2.6.0-dev.20171003
構文: tsc [オプション] [ファイル ...]
例: tsc hello.ts
tsc --outFile file.js file.ts
tsc @args.txt
オプション:
-h, --help このメッセージを表示します。
--all コンパイラ オプションをすべて表示します。
-v, --version コンパイラのバージョンを表示します。
--init TypeScript プロジェクトを初期化して、tsconfig.json ファイルを作成します。
-p ファイルまたはディレクトリ, --project ファイルまたはディレクトリ 構成ファイルか、'tsconfig.json' を含むフォルダーにパスが指定されたプロジェクトをコ
ンパイルします。
--pretty 色とコンテキストを使用してエラーとメッセージにスタイルを適用します (試験的)。
-w, --watch 入力ファイルを監視します。
-t バージョン, --target バージョン ECMAScript のターゲット バージョンを指定します: 'ES3' (既定)、'ES5'、'ES2015'、'ES2016'、'ES2017'、'ES
NEXT'。
-m 種類, --module 種類 モジュール コード生成を指定します: 'none'、'commonjs'、'amd'、'system'、'umd'、'es2015'、'ESNext'。
--lib コンパイルに含めるライブラリ ファイルを指定します:
'es5' 'es6' 'es2015' 'es7' 'es2016' 'es2017' 'esnext' 'dom' 'dom.iterable' 'webworker' 'scripthost' 'es201
5.core' 'es2015.collection' 'es2015.generator' 'es2015.iterable' 'es2015.promise' 'es2015.proxy' 'es2015.reflect' 'es2015.symbol' 'es2015.symbol.wellkno
wn' 'es2016.array.include' 'es2017.object' 'es2017.sharedmemory' 'es2017.string' 'es2017.intl' 'esnext.asynciterable'
--allowJs javascript ファイルのコンパイルを許可します。
--jsx 種類 JSX コード生成を指定します: 'preserve'、'react-native'、'react'。
-d, --declaration 対応する '.d.ts' ファイルを生成します。
--sourceMap 対応する '.map' ファイルを生成します。
--outFile ファイル 出力を連結して 1 つのファイルを生成します。
--outDir ディレクトリ ディレクトリへ出力構造をリダイレクトします。
--removeComments コメントを出力しないでください。
--noEmit 出力しないでください。
--strict strict 型チェックのオプションをすべて有効にします。
--noImplicitAny 暗黙的な 'any' 型を含む式と宣言に関するエラーを発生させます。
--strictNullChecks 厳格な null チェックを有効にします。
--noImplicitThis 暗黙的な 'any' 型を持つ 'this' 式でエラーが発生します。
--alwaysStrict 厳格モードで解析してソース ファイルごとに "use strict" を生成します。
--noUnusedLocals 使用されていないローカルに関するエラーを報告します。
--noUnusedParameters 使用されていないパラメーターに関するエラーを報告します。
--noImplicitReturns 関数の一部のコード パスが値を返さない場合にエラーを報告します。
--noFallthroughCasesInSwitch switch ステートメントに case のフォールスルーがある場合にエラーを報告します。
--types コンパイルに含む型宣言ファイル。
@<ファイル>使用 '// @ts-ignore' 注释抑制 .ts 文件中的错误
TypeScript 2.6 支持在 .ts 文件中使用 // @ts-ignore 注释来抑制错误,该注释应放在有问题的代码行上方。
示例
if (false) {
// @ts-ignore: 无法访问的代码错误
console.log("hello");
}// @ts-ignore 注释会抑制源自下一行的所有错误。 建议在 @ts-ignore 后面的注释中说明正在抑制哪个错误。
请注意,此注释仅抑制错误报告,我们建议你非常谨慎地使用此注释。
更快的 tsc --watch
TypeScript 2.6 带来了更快的 --watch 实现。 新版本针对使用 ES 模块的代码库优化了代码生成和检查。 检测到模块文件中的更改将导致仅重新生成已更改的模块及其依赖的文件,而不是整个项目。 具有大量文件的项目将从这一更改中获得最大收益。
新实现还带来了 tsserver 中监视的性能改进。 监视器逻辑已被完全重写,以更快地响应更改事件。
只写引用现在被标记为未使用
TypeScript 2.6 添加了 noUnusedLocals 和 noUnusedParameters 编译器选项的修订实现。 仅被写入但从未被读取的声明现在被标记为未使用。
示例
下面 n 和 m 都将被标记为未使用,因为它们的值从未被读取。以前 TypeScript 只检查它们的值是否被引用。
function f(n: number) {
n = 0;
}
class C {
private m: number;
constructor() {
this.m = 0;
}
}此外,仅在其自身主体内被调用的函数也被视为未使用。
示例
function f() {
f(); // 错误:'f' 被声明但它的值从未被读取
}