By Francisco Ramos
// 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;// 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}`);
}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) {}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"
}// 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'
};// 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.`;@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) {}
}// Internal modules were always meant to be namespaces
// before
module path.to.some.package {}
// now
namespace path.to.some.package {}