Was this page helpful?

TypeScript 2.2

Support for Mix-in classes

TypeScript 2.2 adds support for the ECMAScript 2015 mixin class pattern (seeMDN 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

Amixin constructor type refers to a type that has a single construct signature with a single rest argument of typeany[] and an object-like return type. For example, given an object-like typeX,new (...args: any[]) => X is a mixin constructor type with an instance typeX.

Amixin class is a class declaration or expression thatextends an expression of a type parameter type. The following rules apply to mixin class declarations:

  • The type parameter type of theextends expression must be constrained to a mixin constructor type.
  • The constructor of a mixin class (if any) must have a single rest parameter of typeany[] and must use the spread operator to pass those parameters as arguments in asuper(...args) call.

Given an expressionBase of a parametric typeT with a constraintX, a mixin classclass C extends Base {...} is processed as ifBase had typeX and the resulting type is the intersectiontypeof 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.

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 signaturenew(s: string) => A & B.

Putting all of the above rules together in an example
ts
classPoint {
constructor(publicx:number,publicy:number) {}
}
classPerson {
constructor(publicname:string) {}
}
typeConstructor<T> =new (...args:any[])=>T;
functionTagged<TextendsConstructor<{}>>(Base:T) {
returnclassextendsBase {
_tag:string;
constructor(...args:any[]) {
super(...args);
this._tag ="";
}
};
}
constTaggedPoint =Tagged(Point);
letpoint =newTaggedPoint(10,20);
point._tag ="hello";
classCustomerextendsTagged(Person) {
accountBalance:number;
}
letcustomer =newCustomer("Joe");
customer._tag ="test";
customer.accountBalance =0;

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 followingWithLocation function implements a subclass factory that adds agetLocation method to any class that satisfies thePoint interface (i.e. that hasx andy properties of typenumber).

ts
interfacePoint {
x:number;
y:number;
}
constWithLocation = <TextendsConstructor<Point>>(Base:T)=>
classextendsBase {
getLocation(): [number,number] {
return [this.x,this.y];
}
};

object type

TypeScript did not have a type that represents the non-primitive type, i.e. any thing that is notnumber,string,boolean,symbol,null, orundefined. Enter the newobject type.

Withobject type, APIs likeObject.create can be better represented. For example:

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

Support fornew.target

Thenew.target meta-property is new syntax introduced in ES2015.When an instance of a constructor is created vianew, the value ofnew.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 vianew,new.target is set toundefined.

new.target comes in handy whenObject.setPrototypeOf or__proto__ needs to be set in a class constructor. One such use case is inheriting fromError in NodeJS v4 and higher.

Example
ts
classCustomErrorextendsError {
constructor(message?:string) {
super(message);// 'Error' breaks prototype chain here
Object.setPrototypeOf(this,new.target.prototype);// restore prototype chain
}
}

This results in the generated JS

js
varCustomError = (function(_super) {
__extends(CustomError,_super);
functionCustomError() {
var_newTarget =this.constructor;
var_this =_super.apply(this,arguments);// 'Error' breaks prototype chain here
_this.__proto__ =_newTarget.prototype;// restore prototype chain
return_this;
}
returnCustomError;
})(Error);

new.target also comes in handy for writing constructable functions, for example:

ts
functionf() {
if (new.target) {
/* called via 'new' */
}
}

Which translates to:

js
functionf() {
var_newTarget =this &&thisinstanceoff ?this.constructor :void0;
if (_newTarget) {
/* called via 'new' */
}
}

Better checking fornull/undefined in operands of expressions

TypeScript 2.2 improves checking of nullable operands in expressions. Specifically, these are now flagged as errors:

  • If either operand of a+ operator is nullable, and neither operand is of typeany orstring.
  • If either operand of a-,*,**,/,%,<<,>>,>>>,&,|, or^ operator is nullable.
  • If either operand of a<,>,<=,>=, orin operator is nullable.
  • If the right operand of aninstanceof operator is nullable.
  • If the operand of a+,-,~,++, or-- unary operator is nullable.

An operand is considered nullable if the type of the operand isnull orundefined or a union type that includesnull orundefined.Note that the union type case only occurs instrictNullChecks mode becausenull andundefined disappear from unions in classic type checking mode.

Dotted property for types with string index signatures

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
interfaceStringMap<T> {
[x:string]:T;
}
constmap:StringMap<number>;
map["prop1"] =1;
map.prop2 =2;

This only applies to types with anexplicit string index signature.It is still an error to access unknown properties on a type using. notation.

Support for spread operator on JSX element children

TypeScript 2.2 adds support for using spread on JSX element children.Please seefacebook/jsx#57 for more details.

Example
ts
functionTodo(prop: {key:number;todo:string }) {
return <div>{prop.key.toString() + prop.todo}</div>;
}
functionTodoList({todos }:TodoListProps) {
return (
<div>{...todos.map(todo=> <Todokey={todo.id}todo={todo.todo} />)}</div>
);
}
letx:TodoListProps;
<TodoList {...x} />;

Newjsx: react-native

React-native build pipeline expects all files to have a.js extension even if the file contains JSX syntax.The newjsx valuereact-native will preserve the JSX syntax in the output file, but give it a.js extension.

The TypeScript docs are an open source project. Help us improve these pagesby sending a Pull Request

Contributors to this page:
MHMohamed Hegazy  (53)
OTOrta Therox  (12)
EIEugene Ilyin  (1)
JBJack Bates  (1)
EBEli Barzilay  (1)
2+

Last updated: Jul 14, 2025