首先,安装tslib实用程序库:
npm install tslib
其次,使用--importHelpers命令编译文件:
tsc --module commonjs --importHelpers a.ts
因此,给定以下输入,生成的.js文件将包含导入到tslib并使用其中的__assign帮助程序而不是内联它。
export const o = { a: 1, name: "o" };
export const copy = { ...o };
"use strict";
var tslib_1 = require("tslib");
exports.o = { a: 1, name: "o" };
exports.copy = tslib_1.__assign({}, exports.o);
无类型的导入
传统上,TypeScript对于如何导入模块过于严格。这是为了避免拼写错误并阻止用户错误地使用模块。
但是,在很多时候,您可能只想导入可能没有自含.d.ts文件的现有模块。以前这是一个错误。从TypeScript 2.1开始,这现在变得更加容易。
使用TypeScript 2.1,您可以导入JavaScript模块而无需类型声明。如果存在类型声明(例如,declare module "foo" { ... },或node_modules/@types/foo)仍然具有优先权。
对没有声明文件的模块的导入仍将被标记为--noImplicitAny下的错误。
示例
// Succeeds if `node_modules/asdf/index.js` exists
import { x } from "asdf";
支持--target ES2016,--target ES2017和--target ESNext
TypeScript 2.1支持三个新的目标值--target ES2016,--target ES2017和--target ESNext。
使用target --target ES2016将指示编译器不要转换特定于ES2016的功能,例如**运算符。
同样,--target ES2017将指示编译器不要转换特定于ES2017的特性,如async/ await。
--target ESNext针对最新支持的ES提议功能。
改进的any推理
以前,如果TypeScript无法确定变量的类型,则会选择any类型。
let x; // implicitly 'any'
let y = []; // implicitly 'any[]'
let z: any; // explicitly 'any'.
使用TypeScript 2.1,而不仅仅是选择any,TypeScript将根据您最后分配的内容推断类型。
仅在设置--noImplicitAny时才启用此选项。
示例
let x;
// You can still assign anything you want to 'x'.
x = () => 42;
// After that last assignment, TypeScript 2.1 knows that 'x' has type '() => number'.
let y = x();
// Thanks to that, it will now tell you that you can't add a number to a function!
console.log(x + y);
// ~~~~~
// Error! Operator '+' cannot be applied to types '() => number' and 'number'.
// TypeScript still allows you to assign anything you want to 'x'.
x = "Hello world!";
// But now it also knows that 'x' is a 'string'!
x.toLowerCase();
现在也对空数组进行了相同类型的跟踪。
声明为没有类型注释且初始值为[]的变量被视为隐式any[]变量。然而,每个后续的x.push(value),x.unshift(value)或者x[n] = value操作根据添加到的元素来演变变量的类型。
function f1() {
let x = [];
x.push(5);
x[1] = "hello";
x.unshift(true);
return x; // (string | number | boolean)[]
}
function f2() {
let x = null;
if (cond()) {
x = [];
while (cond()) {
x.push("hello");
}
}
return x; // string[] | null
}
隐含任何错误
这样做的一个很大好处是,在运行--noImplicitAny时你会看到更少的隐式any错误。仅当编译器无法知道没有类型注释的变量类型时,才会报告隐式any错误。
示例
function f3() {
let x = []; // Error: Variable 'x' implicitly has type 'any[]' in some locations where its type cannot be determined.
x.push(5);
function g() {
x; // Error: Variable 'x' implicitly has an 'any[]' type.
}
}
更好地推断文字类型
字符串,数字和布尔文字类型(例如"abc",1和true)仅在存在显式类型注释时才推断。从TypeScript 2.1开始,始终为const变量和readonly属性推断文字类型。
为没有类型注释的const变量或readonly属性推断的类型是文字初始值设定项的类型。为具有初始值设定项且没有类型注释的let变量,var变量,参数或非readonly属性推断的类型是初始化程序的扩展文字类型。对于字符串文字类型的加宽类型是string,number对于数字文字类型,boolean对于true或false,以及包含枚举文字类型的枚举。
示例
const c1 = 1; // Type 1
const c2 = c1; // Type 1
const c3 = "abc"; // Type "abc"
const c4 = true; // Type true
const c5 = cond ? 1 : "abc"; // Type 1 | "abc"
let v1 = 1; // Type number
let v2 = c2; // Type number
let v3 = c3; // Type string
let v4 = c4; // Type boolean
let v5 = c5; // Type number | string
可以通过显式类型注释来控制文字类型扩展。具体来说,当为没有类型注释的const位置推断出文字类型的表达式时,该const变量将推断出一个加宽的文字类型。但是,当const位置具有显式文字类型注释时,该const变量将获得非加宽文字类型。
示例
const c1 = "hello"; // Widening type "hello"
let v1 = c1; // Type string
const c2: "hello" = "hello"; // Type "hello"
let v2 = c2; // Type "hello"
使用超级调用的返回值为'this'
在ES2015中,返回对象的构造函数隐式地将this值替换为super()的任何调用者。因此,有必要捕获super()的任何潜在返回值,并且使用this替换它。此更改允许使用Custom Elements,该元素利用此特性用用户编写的构造函数初始化浏览器分配的元素。
示例
class Base {
x: number;
constructor() {
// return a new object other than `this`
return {
x: 1,
};
}
}
class Derived extends Base {
constructor() {
super();
this.x = 2;
}
}
输出:
var Derived = (function (_super) {
__extends(Derived, _super);
function Derived() {
var _this = _super.call(this) || this;
_this.x = 2;
return _this;
}
return Derived;
}(Base));
这种变化导致扩展内置类(如,Error,Array,Map,等)的行为中断。配置继承
通常,一个项目有多个输出目标,例如ES5和ES2015,调试和生产,CommonJS和System;这两个目标之间只有少数配置选项发生变化,维护多个tsconfig.json文件可能很麻烦。
TypeScript 2.1支持使用extends继承配置,其中:
- extends是tsconfig.json中一个新的顶级属性(包括compilerOptions,files,include,和exclude)。
- extends的值必须是包含要继承的另一个配置文件的路径的字符串。
- 首先加载基本文件中的配置,然后由继承配置文件中的配置覆盖。
- 不允许配置文件之间的循环。
- files,include和exclude从继承配置文件覆盖基本配置文件中的那些。
- 配置文件中找到的所有相对路径将相对于它们所源自的配置文件进行解析。
示例
configs/base.json:
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true
}
}
tsconfig.json:
{
"extends": "./configs/base",
"files": [
"main.ts",
"supplemental.ts"
]
}
tsconfig.nostrictnull.json:
{
"extends": "./tsconfig",
"compilerOptions": {
"strictNullChecks": false
}
}
新 --alwaysStrict
使用--alwaysStrict调用编译器的原因:
- 以严格模式解析所有代码。
- 在每个生成的文件上面写入指令"use strict";。
模块在严格模式下自动解析。对于非模块代码,建议使用新标志。
标签:TypeScript
相关阅读 >>
更多相关阅读请进入《typescript》频道 >>
Vue.js 设计与实现 基于Vue.js 3 深入解析Vue.js 设计细节
本书对 Vue.js 3 技术细节的分析非常可靠,对于需要深入理解 Vue.js 3 的用户会有很大的帮助。——尤雨溪,Vue.js作者