支持混合类
¥Support for Mix-in classes
TypeScript 2.2 增加了对 ECMAScript 2015 mixin 类模式的支持(更多详情请参阅 MDN Mixin 描述 和 “实际” 与 JavaScript 类的混合),以及在交叉类型中将 mixin 构造签名与常规构造签名相结合的规则。
¥TypeScript 2.2 adds support for the ECMAScript 2015 mixin class pattern (see MDN Mixin description and “Real” Mixins with JavaScript Classes for more details) as well as rules for combining mixin construct signatures with regular construct signatures in intersection types.
首先介绍一些术语
¥First some terminology
混合构造函数类型是指具有单个构造函数签名的类型,该签名包含一个 any[]
类型的剩余参数和一个类似对象的返回类型。例如,给定一个类似对象的类型 X
,new (...args: any[]) => X
是一个混合构造函数类型,其实例类型为 X
。
¥A mixin constructor type refers to a type that has a single construct signature with a single rest argument of type any[]
and an object-like return type. For example, given an object-like type X
, new (...args: any[]) => X
is a mixin constructor type with an instance type X
.
混合类是一种类声明或表达式,它 extends
是类型参数类型的表达式。以下规则适用于 mixin 类声明:
¥A mixin class is a class declaration or expression that extends
an expression of a type parameter type. The following rules apply to mixin class declarations:
-
extends
表达式的类型参数类型必须限制为混合构造函数类型。¥The type parameter type of the
extends
expression must be constrained to a mixin constructor type. -
混合类的构造函数(如果有)必须具有一个
any[]
类型的剩余参数,并且必须使用展开运算符将这些参数作为super(...args)
调用中的参数传递。¥The constructor of a mixin class (if any) must have a single rest parameter of type
any[]
and must use the spread operator to pass those parameters as arguments in asuper(...args)
call.
给定一个表达式 Base
,其参数类型为 T
,且具有约束 X
,则混合类 class C extends Base {...}
将被处理为 Base
具有类型 X
,并且结果类型为交叉 typeof C & T
。换句话说,混合类表示为混合类构造函数类型和参数基类构造函数类型的交叉。
¥Given an expression Base
of a parametric type T
with a constraint X
, a mixin class class C extends Base {...}
is processed as if Base
had type X
and the resulting type is the intersection typeof C & T
.
In other words, a mixin class is represented as an intersection between the mixin class constructor type and the parametric base class constructor type.
当获取包含混合构造函数类型的交叉类型的构造函数签名时,混合构造函数签名将被丢弃,其实例类型将混合到交叉类型中其他构造函数签名的返回类型中。例如,交叉类型 { new(...args: any[]) => A } & { new(s: string) => B }
具有单个构造签名 new(s: string) => A & B
。
¥When obtaining the construct signatures of an intersection type that contains mixin constructor types, the mixin construct signatures are discarded and their instance types are mixed into the return types of the other construct signatures in the intersection type.
For example, the intersection type { new(...args: any[]) => A } & { new(s: string) => B }
has a single construct signature new(s: string) => A & B
.
将以上所有规则整合到一个示例中
¥Putting all of the above rules together in an example
ts
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
接口的类(即具有 number
类型属性的 x
和 y
)。
¥Mixin classes can constrain the types of classes they can mix into by specifying a construct signature return type in the constraint for the type parameter.
For example, the following WithLocation
function implements a subclass factory that adds a getLocation
method to any class that satisfies the Point
interface (i.e. that has x
and y
properties of type number
).
ts
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
类型
¥object
type
TypeScript 没有表示非原始类型的类型,即任何非 number
、string
、boolean
、symbol
、null
或 undefined
的类型。输入新的 object
类型。
¥TypeScript did not have a type that represents the non-primitive type, i.e. any thing that is not number
, string
, boolean
, symbol
, null
, or undefined
. Enter the new object
type.
使用 object
类型,可以更好地表示像 Object.create
这样的 API。例如:
¥With object
type, APIs like Object.create
can be better represented. For example:
ts
declare function create(o: object | null): void;create({ prop: 0 }); // OKcreate(null); // OKcreate(42); // Errorcreate("string"); // Errorcreate(false); // Errorcreate(undefined); // Error
支持 new.target
¥Support for new.target
new.target
元属性是 ES2015 中引入的新语法。当通过 new
创建构造函数实例时,new.target
的值将被设置为最初用于分配实例的构造函数的引用。如果函数是通过 new
调用而不是构造的,则 new.target
会被设置为 undefined
。
¥The new.target
meta-property is new syntax introduced in ES2015.
When an instance of a constructor is created via new
, the value of new.target
is set to be a reference to the constructor function initially used to allocate the instance.
If a function is called rather than constructed via new
, new.target
is set to undefined
.
当需要在类构造函数中设置 Object.setPrototypeOf
或 __proto__
时,new.target
非常方便。一个这样的用例是在 NodeJS v4 及更高版本中继承 Error
。
¥new.target
comes in handy when Object.setPrototypeOf
or __proto__
needs to be set in a class constructor. One such use case is inheriting from Error
in NodeJS v4 and higher.
示例
¥Example
ts
class CustomError extends Error {constructor(message?: string) {super(message); // 'Error' breaks prototype chain hereObject.setPrototypeOf(this, new.target.prototype); // restore prototype chain}}
生成的 JS 代码如下
¥This results in the generated JS
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 chainreturn _this;}return CustomError;})(Error);
new.target
在编写可构造函数时也非常有用,例如:
¥new.target
also comes in handy for writing constructable functions, for example:
ts
function f() {if (new.target) {/* called via 'new' */}}
翻译为:
¥Which translates to:
js
function f() {var _newTarget = this && this instanceof f ? this.constructor : void 0;if (_newTarget) {/* called via 'new' */}}
更好地检查表达式操作数中的 null
/undefined
¥Better checking for null
/undefined
in operands of expressions
TypeScript 2.2 改进了表达式中可空操作数的检查。具体来说,以下情况现在会被标记为错误:
¥TypeScript 2.2 improves checking of nullable operands in expressions. Specifically, these are now flagged as errors:
-
如果
+
运算符的任一操作数可空,且两个操作数均不属于any
或string
类型。¥If either operand of a
+
operator is nullable, and neither operand is of typeany
orstring
. -
如果
-
、*
、**
、/
、%
、<<
、>>
、>>>
、&
、|
或^
运算符的任一操作数可空。¥If either operand of a
-
,*
,**
,/
,%
,<<
,>>
,>>>
,&
,|
, or^
operator is nullable. -
如果
<
、>
、<=
、>=
或in
运算符的任一操作数可空。¥If either operand of a
<
,>
,<=
,>=
, orin
operator is nullable. -
如果
instanceof
运算符的右操作数可空。¥If the right operand of an
instanceof
operator is nullable. -
如果
+
、-
、~
、++
或--
一元运算符的操作数可为空。¥If the operand of a
+
,-
,~
,++
, or--
unary operator is nullable.
如果操作数的类型为 null
或 undefined
,或者为包含 null
或 undefined
的联合类型,则该操作数被视为可空。请注意,联合类型情况仅发生在 strictNullChecks
模式下,因为在经典类型检查模式下,null
和 undefined
会从联合中消失。
¥An operand is considered nullable if the type of the operand is null
or undefined
or a union type that includes null
or undefined
.
Note that the union type case only occurs in strictNullChecks
mode because null
and undefined
disappear from unions in classic type checking mode.
带有字符串索引签名的类型的点属性
¥Dotted property for types with string index signatures
带有字符串索引签名的类型可以使用 []
表示法进行索引,但不允许使用 .
表示法。从 TypeScript 2.2 开始,应该允许使用其中任何一种。
¥Types with a string index signature can be indexed using the []
notation, but were not allowed to use the .
.
Starting with TypeScript 2.2 using either should be allowed.
ts
interface StringMap<T> {[x: string]: T;}const map: StringMap<number>;map["prop1"] = 1;map.prop2 = 2;
这仅适用于具有显式字符串索引签名的类型。使用 .
表示法访问类型的未知属性仍然是错误的。
¥This only applies to types with an explicit string index signature.
It is still an error to access unknown properties on a type using .
notation.
支持 JSX 元素子元素上的展开运算符
¥Support for spread operator on JSX element children
TypeScript 2.2 增加了对 JSX 元素子元素使用展开的支持。有关更多详细信息,请参阅 facebook/jsx#57。
¥TypeScript 2.2 adds support for using spread on JSX element children. Please see facebook/jsx#57 for more details.
示例
¥Example
ts
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
¥New jsx: react-native
React-native 构建管道要求所有文件都具有 .js
扩展名,即使文件包含 JSX 语法也是如此。新的 jsx
值 react-native
将在输出文件中保留 JSX 语法,但赋予其 .js
扩展名。
¥React-native build pipeline expects all files to have a .js
extension even if the file contains JSX syntax.
The new jsx
value react-native
will preserve the JSX syntax in the output file, but give it a .js
extension.