TypeScript 2.2

TypeScript 2.2

支持混合类

TypeScript 2.2 添加了对 ECMAScript 2015 mixin 类模式的支持(请参阅 MDN Mixin 描述带有 JavaScript 类的“Real”Mixins 以获取更多详细信息)以及将 mixin 构造签名与交集类型中的常规构造签名组合在一起的规则。

首先是一些术语

一个混入构造型是指具有与类型的单个参数其余的单个构建签名类型any[]和类似对象的返回类型。例如,给定一个类似于对象的类型X,new (...args: any[]) => X是一个带有实例类型的mixin构造函数类型X。

一个混合类是一类声明或表达式extends的类型参数类型的表达式。以下规则适用于 mixin 类声明:

  • extends表达式的类型参数类型必须被约束为一个 mixin 构造函数类型。

  • mixin 类的构造函数(如果有的话)必须具有一个any[]类型的 rest 参数,并且必须使用 spread 运算符将这些参数作为参数传递给super(...args)调用。

给定具有X约束的T参数类型的表达式Base,混合类将class C extends Base {...}像处理Base类型一样进行处理,结果X类型为typeof C & T交集。换句话说,mixin 类表示为 mixin 类构造函数类型和参数基类构造函数类型之间的交集。

当获得包含mixin构造函数类型的交集类型的构造签名时,mixin构造签名将被丢弃,并且它们的实例类型将被混合到交集类型中其他构造签名的返回类型中。例如,交集类型{ new(...args: any[]) => A } & { new(s: string) => B }具有单个构造签名new(s: string) => A & B。

将所有上述规则放在一个示例中

class Point { constructor(public x: number, public y: number) {} } class Person { constructor(public name: string) {} } type Constructor<T> = new(...args: any[]) => T; function Tagged<T extends Constructor<{}>>(Base: T) { return class extends Base { _tag: string; constructor(...args: any[]) { super(...args this._tag = ""; } } } const TaggedPoint = Tagged(Point let point = new TaggedPoint(10, 20 point._tag = "hello"; class Customer extends Tagged(Person) { accountBalance: number; } let customer = new Customer("Joe" customer._tag = "test"; customer.accountBalance = 0;

Mixin 类可以通过在类型参数的约束中指定构造体签名返回类型来约束它们可以混入的类的类型。例如,下面的WithLocation函数实现了一个子类工厂,它将一个getLocation方法添加到满足该Point接口的任何类(即具有类型xy属性的number类)。

interface Point { x: number; y: number; } const WithLocation = <T extends Constructor<Point>>(Base: T) => class extends Base { getLocation(): [number, number] { return [this.x, this.y]; } }

object 类型

TypeScript 没有表示非基本类型,即不是任何事情型numberstringbooleansymbolnull,或undefined。输入新的object类型。

使用object类型,API 像Object.create可以更好地表示 。例如:

declare function create(o: object | null): void; create{ prop: 0 } // OK create(null // OK create(42 // Error create("string" // Error create(false // Error create(undefined // Error

支持 new.target

new.target元属性是 ES2015 引入了新的语法。当通过new创建构造函数的实例时,其值new.target被设置为最初用于分配实例的构造函数的引用。如果一个函数被调用而不是通过构造newnew.target被设置为undefined

在需要Object.setPrototypeOf或者__proto__需要在类构造器中设置时new.target派上用场。一个这样的用例是从 NodeJS v4 和更高版本Error继承而来的。

示例

class CustomError extends Error { constructor(message?: string) { super(message // 'Error' breaks prototype chain here Object.setPrototypeOf(this, new.target.prototype // restore prototype chain } }

这会导致生成的 JS

var CustomError = (function (_super) { __extends(CustomError, _super function CustomError() { var _newTarget = this.constructor; var _this = _super.apply(this, arguments // 'Error' breaks prototype chain here _this.__proto__ = _newTarget.prototype; // restore prototype chain return _this; } return CustomError; })(Error

new.target 也可用于编写可构建的功能,例如:

function f() { if (new.target) { /* called via 'new' */ } }

其转化为:

function f() { var _newTarget = this && this instanceof f ? this.constructor : void 0; if (_newTarget) { /* called via 'new' */ } }

更好地检查null/ undefined表达式中的操作数

TypeScript 2.2 改进了对表达式中可空操作数的检查。具体来说,这些现在被标记为错误:

  • 如果运算+符的任何一个操作数都是可以为空的,并且这两个操作数都不是类型anystring

  • 如果一个操作数-,*,**,/,%,<<,>>,>>>,&,|,或^运算符可为空。

  • 如果一个操作数<,>,<=,>=,或in运算符可为空。

  • 如果操作instanceof运算符的右操作数是可空的。

  • 如果一个操作数+-~++,或--一元运算符可为空。

如果操作数的类型是null或者 undefined或者包含null或者联合类型,则操作数被认为是可空的undefined。需要注意的是联合类型情况下,只只发生在--strictNullChecks模式,因为nullundefined在经典型检查模式工会消失。

具有字符串索引签名的类型的虚线属性

带有字符串索引签名的类型可以使用[]符号进行索引,但不允许使用该符号.。应该允许从 TypeScript 2.2 开始。

interface StringMap<T> { [x: string]: T; } const map: StringMap<number>; map["prop1"] = 1; map.prop2 = 2;

这仅适用于具有显式字符串索引签名的类型。使用.表示法访问类型上的未知属性仍然是错误的。

支持 JSX 元素子元素上的扩展运算符

TypeScript 2.2 增加了对在 JSX 元素上使用传播的支持。

示例

function Todo(prop: { key: number, todo: string }) { return <div>{prop.key.toString() + prop.todo}</div>; } function TodoList{ todos }: TodoListProps) { return <div> {...todos.map(todo => <Todo key={todo.id} todo={todo.todo} />)} </div>; } let x: TodoListProps; <TodoList {...x} />

新 jsx: react-native

.js即使文件包含 JSX 语法,React-native 构建管道也期望所有文件都具有扩展名。新的--jsxreact-native将继续输出文件中的 JSX 语法,但给它一个.js扩展。