What's new
in
TypeScript 1.5
By Francisco Ramos
Most relevant features
- Destructuring
- Spread operator
- ES6 Modules
- for..of loops
- Symbols
- Computed properties
- let and const declaration
- Tagged templates
- ES7 Decorators
- namespace keyword
Destructuring
Array destructuring
// Simple example
var foo = ["one", "two", "three"];
// without destructuring
var one = foo[0];
var two = foo[1];
var three = foo[2];
// with destructuring
var [one, two, three] = foo;
// Swapping variables
var a = 1;
var b = 3;
[a, b] = [b, a];
// Multiple-value returns
function baa() {
return [1, 2];
}
var [a, b] = baa();
// Ignoring some returned values
function baz() {
return [1, 2, 3];
}
var [a, , b] = baz();
// Simple example
var person = {name: 'Fran', age: 36};
// without destructuring
var name = person.name;
var age = person.age;
// with destructuring
var {name, age} = person;
Object destructuring
// Function arguments
// without destructuring
function doAjax(params) {
var url = params.url;
var method = params.method || 'POST';
var async = !!params.async;
var callback = params.callback;
}
// with destructuring
function doAjax({url, method = 'POST', async = true, callback}) {
console.log(url); // "http://www.example.com"
console.log(method); // "POST"
console.log(async); // true
}
doAjax({
url: 'http://www.example.com',
callback(data) {}
});
// Nested object and array destructuring
var Company = {
name: "Franchu Inc.",
location: [12, -56],
departments: [
{
name: "IT",
description: "It does IT stuff"
team: [
{
name: "Fran",
age: 36,
position: "Expert Frontend"
}
]
},
]
};
var {departments: [name: department, team: [employee]]} = Company;
console.log(department); // "IT"
console.log(employee); // {name: "Fran", age: 36, position: "Expert Frontend"}
// Iteration and destructuring
var people = [
{
name: "Mike Smith",
family: {
mother: "Jane Smith",
father: "Harry Smith",
sister: "Samantha Smith"
},
age: 35
},
{
name: "Tom Jones",
family: {
mother: "Norah Jones",
father: "Richard Jones",
brother: "Howard Jones"
},
age: 25
}
];
for (var {name, family: {father}} of people) {
console.log(`name: ${name}, father: ${father}`);
}
Spread operator
var myArray = [1, 2, 3, 4];
// function calls
boo(...myArray);
// better than => boo.apply(null, myArray);
// array literals
[...myArray, 5, 6, 7];
// better than => [].concat(myArray).concat([5, 6, 7]);
// destructuring
var a, b, others = [];
[a, b, ...others] = [1, 2, 3, 4, 5]; // a = 1, b = 2, others = [3, 4, 5]
// Better apply
function myFunction(x, y, z) { }
var args = [0, 1, 2];
// without spread operator
myFunction.apply(null, args);
// with spread operator
myFunction(...args);
// A more powerful array literal
var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
console.log(lyrics); // ["head", "shoulders", "knees", "and", "toes"]
// Apply for new
var dateFields = readDateFields(database);
var date = new Date(...dateFields);
// A better push
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// without spread operator
Array.prototype.push.apply(arr1, arr2);
// with spread operator
arr1.push(...arr2);
// Combined with rest operator
function doSomething (x: number, y: number, ...others: number[]) {
// does something with "x" and "y";
return x + y + doSomethingElse(...others);
}
function doSomethingElse(...args) {}
ES6 Modules
TO-DO
for..of loops
var DeveloperTeam = [{
name: 'Degu',
position: 'Lead Developer'
}, {
name: 'Angelo',
position: 'Backend'
}, {
name: 'Philipp',
position: 'Frontend'
}];
// ES3 way
for (var i = 0, len = Team.length; i < len; i++) {
var developer = DeveloperTeam[i];
}
// ES5 way
DeveloperTeam.forEach(function (developer) {
// remember "this" is pointing to "window" here
});
// New way
for (var developer of DeveloperTeam) {}
// Difference between for...of and for...in
var arr = [3, 5, 7];
arr.foo = 'hello';
for (var i in arr) {
console.log(i); // logs "0", "1", "2", "foo"
}
for (var i of arr) {
console.log(i); // logs "3", "5", "7"
}
Symbols
TO-DO
Computed properties
// before
var myObject = {
prop: 'property',
doSomething: function () {}
};
myObject['prop_' + getNewProperty()] = 'extra property';
// now
var myObject = {
prop: 'property',
doSomething() {}, // since TS 1.x
[`prop_${getNewProperty()}`]: 'extra property'
};
let and const declaration
TO-DO
Tagged templates
// Template literals (introduced in TS 1.4)
var name = 'Fran';
var age = 36;
var job = 'Frontend developer';
// supports interpolation
console.log(`Employee's name: ${name}, whose age is ${age} and job: ${job}`);
// multiple line support
var info = `
Employee Info
-------------
Name: ${name}
Age: ${age}
Position: ${job}
`;
// Tagged templates
tagFunction`Hello ${firstName} ${lastName}!`;
function tagFunction(literals: string[], ...values: any[]): string;
// Manipulate the string result
var a = 3, b = 4;
var result = multiply`The result of multiplying ${a} by ${b} is`);
console.log(result); // "The result of multiplying 3 by 4 is 12"
// Internationalization
var translation = {
de: {
'Hello {0}, you have {1} in your bank account.': 'Hallo {0}, Sie haben {1} auf Ihrem Bankkonto.'
},
es: {
'Hello {0}, you have {1} in your bank account.': 'Hola {0}, tiene {1} en su cuenta.'
}
}
//////////////////////////////////////////////////////////////
var name = 'Bob';
var amount = 100;
i18n`Hello ${name}, you have ${amount} in your bank account.`;
ES7 Decorators
@myClassDecorator
class MyComponent {
@myPropertyDecorator
property: string;
@myMethodDecorator
method(@myParameterDecorator param: string) {}
}
/**
* @param target - MyComponent
*/
function myClassDecorator(target: Function): Function {}
/**
* @param target - MyComponent.prototype
* @param key - MyComponent.prototype['property']
*/
function myPropertyDecorator(target: Object, key: string): void {}
/**
* @param target - MyComponent.prototype
* @param key - MyComponent.prototype['method']
* @param descriptor - {value, enumerable, configurable, writable, ...}
*/
function myMethodDecorator(target: Object, key: string, descriptor: Descriptor): void {}
/**
* @param target - MyComponent.prototype
* @param key - MyComponent.prototype['method']
* @param paramIndex - MyComponent.prototype['method'] = function (...params) {}
*/
function myParameterDecorator(target: Object, key: string, paramIndex: number): void {}
@inject(Http, Language) // dependency injection through static annotation
class CoolWidget {
private http: Http;
private lang: Language;
@log // will log any change of state (setter and getter interception)
public state: State;
@readonly // will set "writable" to false
public name: string;
constructor(http: Http, lang: Language) {
this.http = http;
this.lang = lang;
}
@autobind // forces context to be "this"
doSomething() {...}
@debounce(500) // 500 milliseconds debounce
click(e: Event) {...}
// will store all the values passed in as metadata
beCool(@remember how: HowToBeCool) {}
}
namespace keyword
// Internal modules were always meant to be namespaces
// before
module path.to.some.package {}
// now
namespace path.to.some.package {}
Learn More
- ES6 features by Luke Hoban
- ES6 learning by Eric Douglas
- Destructuring and parameter handling in ES6 by Alex Rauschmayer
- Getting literal with ES6 Template String by Addy Osmani
- Symbols in ES6 by Alex Rauschmayer
- ES6 Modules and syntax by Alex Rauschmayer
- Exploring ES7 Decorators by Addy Osmani
- Decorators & metadata reflection in TypeScript
- TypeScript roadmap
What's new in TypeScript 1.5
By Francisco Ramos
What's new in TypeScript 1.5
- 1,144