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

What's new in TypeScript 1.5

By Francisco Ramos

What's new in TypeScript 1.5

  • 1,144