TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
Any browser. Any host. Any OS. Open Source.
Anders Hejlsberg, lead architect of C# and creator of Delphi and
Turbo Pascal, has been working on the development of
TypeScript
I'm on the edge!
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript
ES5
ES2015
ES2016
TS
ES+
Note: there are hundreds of other solutions...
https://github.com/jashkenas/coffeescript/wiki/list-of-languages-that-compile-to-js
May '95
Dec '95
Sep '95
1997
Aug '96
1999
1998
2009
2003
2015
2011
2016
Mocha (Brendan Eich, Netscape)
LiveScript
JavaScript
Edition 1
JScript (Microsoft)
Edition 2
Edition 3
Edition 4
Edition 5
Edition 5.1
Edition 6
Edition 7
ECMA-262 specification
class Client {
constructor(firstname, lastname) {
this.id = undefined
this.firstname = firstname
this.lastname = lastname
}
getFullName() {
return this.firstname + this.lastname
}
generateId() {
this.id = generateGuid()
}
}
class Client {
constructor(firstname, lastname) {
this.id = undefined
this.firstname = firstname
this.lastname = lastname
}
getFullName() {
return this.firstname + this.lastname
}
generateId() {
this.id = generateGuid()
}
static generateGuid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1)
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4()
}
}
ES6 introduces the 'extend' keyword
class TCSClient extends Client {
this.evalSystem = "TCS"
}
ES6
class TCSClient extends Client {
getFullName() {
return this.firstname + " " +
this.lastname
}
}
ES6
Can override functions by re-implementing them in child class
class ClientService {
clients = [];
addClient(client) {
this.clients.add(client);
}
}
export ClientService;
import {ClientService} from './ClientService';
class ClientComponent {
submitClient(client) {
ClientService.addClient(client);
}
}
In ES6 each module is defined in its own file. The functions or variables defined in a module are not visible outside unless you explicitly export them.
main.js
ClientService.js
var x = 1;
if (x) {
let x = 2;
}
console.log(x);
> 1
ES6
Console
const stuff = { things: ['chair', 'desk', 'computer'] };
const stuff = { things: ['chair', 'desk', 'computer'] };
stuff = {}; // fails
console.log(stuff.things); // ...
const stuff = { things: ['chair', 'desk', 'computer'] };
stuff.things.push('pot plant');
console.log(stuff.things);
// chair,desk,computer,pot plant
var arrow = function() {}
var arrow = () => {}
becomes
function() {}
() => {}
becomes
function(a) { return a * a }
a => a * a
becomes
function(a, b) { return a + b }
(a, b) => a + b
becomes
function Counter() {
this.seconds = 0;
setInterval(function() {
this.seconds++
}.bind(this), 1000);
}
function Counter() {
this.seconds = 0;
setInterval(() => this.seconds++, 1000);
}
ES5
ES6
var text = `
This is a template literal
'It can span multiple lines'
"And can contain quotation marks"
`
var text = (
'This is the old method\n' +
'for strings spanning\n' +
'several lines'
)
var text = [
'Or',
'perhaps',
'this'
].join('\n')
ES5
ES6
var text = `the time and date is ${new Date().toLocaleString()}`
var a = 6;
console.log(`The number is ${a}`)
Can interpolate expressions with ${expression}
let myObject = { foo:'bar', baz: 'qux' };
//....
let { foo, baz } = myObject
console.log(foo) // 'bar'
console.log(baz) // 'qux'
An object literal lets us create multiple properties at the same time
An object pattern lets us extract multiple properties at the same time
Properties mapped to aliases
function swapIf () {
var left = 10;
var right = 20;
var aux;
if(right > left) {
aux = right;
right = left;
left = aux;
}
}
function swapIf () {
var left = 10
var right = 20
if(right > left) {
[left, right] = [right, left]
}
}
Can swap variables without need for a temporary variable
ES5
ES6
function displayNameAge ( {name, age} ) {
console.log(`${name} is ${age} years old`)
}
displayNameAge( { age: 27, name: 'John'} ) // 'John is 27 years old'
Can destructure a function's parameter list
function getCoordinates() {
return {
x: 5,
y: 22
}
}
var {x, y} = getCoords()
console.log(x) // 5
console.log(y) // 22
function getCoordinates() {
return {
x: 5,
y: 22
}
}
var object = getCoordinates();
var x = object.x;
var y = object.y;
console.log(x) // 5
console.log(y) // 22
Possible use cases
More terse interaction with returned objects
ES5
ES6
Dynamic
Static
JavaScript, Python,
Ruby, PHP
C, C++, C#, Java, Fortran, Haskell
var number = 5;
number = "Hello!";
//👍np, bro!
int a = 10;
a = "Hello!";
//🔥Compiler Error
function numberCruncher (numA, numB){
return numA + numB;
}
var result = numberCruncher(5, 5);
console.log(result);
>> 10
result = numberCruncher(5, true);
console.log(result);
>> 6 😒
result = numberCruncher(5, 'js4lyfe');
console.log(result);
>> "5js4lyfe" 😁
result = numberCruncher(5, {param: true});
console.log(result);
>> "5[object Object]" 👀🔫
function myTypedFunction(paramName : dataType) : returnType {
// Regular junk here
}
var varName : string = 'Yeah baby!';
Type a variable:
Type a function:
function trimLength(inputVal : string) : number {
return inputVal.trim().length;
}
Available Types:
Standard JS Types: Boolean, Number, String, Array
Also includes Enum, Any, Void
function initSomething() : void {
doSomeStuff();
}
var pointless = initSomething(); // 🍋Compiler Error
var foo : any;
declare var jQuery : any;
jQuery.get('/awesome.html');
foo = 'Hello!';
foo = true;
foo = 42;
export interface UserPositionInfo {
jobFunctionId?: number;
title?: string;
level: number;
}
export interface SidebarItem {
name?: string;
iconUrl?: string;
applicationUrl?: string;
}
export interface AppContextVM {
userId: number;
userName?: string;
isDev: boolean;
currentPosition?: UserPositionInfo;
sidebarItems?: SidebarItem[];
}
Cons
Pros
Plus
/**
* @param {string} msg Message to display.
*/
function Display(msg) {
console.log(msg);
}
/**
* @param {boolean} [loud=false] Greet "loudly".
*/
function Greet(loud) {
if (typeof loud === 'undefined') {
loud = false;
}
var msg = "Hello World";
console.log(loud ? msg.toUpperCase() : msg);
}
/**
* @param msg Message to display.
*/
function Display(msg: string) {
console.log(msg);
}
/**
* @param loud Greet "loudly".
*/
function Greet(loud: boolean = false) {
var msg = "Hello World";
console.log(loud ? msg.toUpperCase() : msg);
}
function Display(msg) {
console.log(msg);
}
function Greet(loud) {
if (typeof loud === 'undefined') {
loud = false;
}
var msg = "Hello World";
console.log(loud ? msg.toUpperCase() : msg);
}
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
/**
* @class Person
* @param {string} name
* @param {number} age
*/
function Person(name, age) {
/**
* @name Person#name
* @type string
*/
this.name = name;
/**
* @name Person#age
* @type number
*/
this.age = age;
}
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person("Dima", 23);
person.talks()
Uncaught TypeError: undefined is not a function
Property 'talks' does not exist on type 'Person'.
var num: number = 123;
function identity(num: number): number {
return num;
}
identity('string'); // error!
var myNumbers : number[] = [170, 2.6, 2245, 3032, 400];
var n: number = null; // Primitives can be null
var x = null; // Same as x: any = null
var x: void = null; // Correct
x = 2; // Error
var e: Null; // Error, can't reference Null type
function initSomething() : void {
doSomeStuff();
}
var pointless = initSomething(); // Compiler Error
// if you absolutely have to (don't do it young Jedi!)
var foo : any;
foo = 'Hello!';
foo = true;
foo = 42;
function fullName(firstName: string, lastName: string) {
return firstName + " " + lastName;
}
var result1 = fullName("Bob"); //error, too few parameters
var result2 = fullName("Bob", "Adams", "Sr."); //error, too many parameters
var result3 = fullName("Bob", "Adams"); //ah, just right
function fullName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
var result1 = fullName("Bob"); //works correctly now
var result2 = fullName("Bob", "Adams", "Sr."); //error, too many parameters
var result3 = fullName("Bob", "Adams"); //ah, just right
buildName(firstName: string, lastName?: string {
if (lastName) {
return firstName + ' ' + lastName;
} else {
return firstName;
}
}
let result1 = buildName('Steve'); // 'Steve'
let result2 = buildName('Steve', 'Hartzog'); // 'Steve Hartzog'
// Compiler error, too many parameters
let result3 = buildName('Steve', 'Hartzog', 'Jr.');
function fullName(firstName: string, lastName = "Smith") {
return firstName + " " + lastName;
}
var result1 = fullName("Bob"); //works correctly now, also
var result2 = fullName("Bob", "Adams", "Sr."); //error, too many parameters
var result3 = fullName("Bob", "Adams"); //ah, just right
function buildName(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
var employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
add(point: Point) {
return new Point(this.x + point.x, this.y + point.y);
}
}
class Person {
constructor(name) {
this.name = name;
}
greet() {
return 'My name is ' + this.name;
}
}
var annabelle = new Person('Annabelle');
console.log(annabelle.greet());
// > My name is Annabelle
class Person {
constructor(public name: string) { }
greet(): string {
return 'My name is ' + this.name;
}
}
var annabelle = new Person('Annabelle');
console.log(annabelle.greet());
// > My name is Annabelle
ES6
TypeScript
class Point3D extends Point {
z: number;
constructor(x: number, y: number, z: number) {
super(x, y);
this.z = z;
}
add(point: Point3D) {
var point2D = super.add(point);
return new Point3D(point2D.x, point2D.y, this.z + point.z);
}
}
class FooBase {
public x: number;
private y: number;
protected z: number;
}
// EFFECT ON INSTANCES
var foo = new FooBase();
foo.x; // okay
foo.y; // ERROR : private
foo.z; // ERROR : protected
class FooChild extends FooBase {
constructor(){
super();
this.x; // okay
this.y; // ERROR: private
this.z; // okay
}
}
interface IPlant{
name: string;
genus: string;
category: string;
}
var plant: IPlant;
plant = new Plant();
class Plant{
name: string;
genus: string;
category: string;
}
class tree implements IPlant {
name: string;
genus: string;
category: string;
}
// TypeScript would produce an error
// because the "flowers" class does not
// implement a "genus" category
class flowers implements IPlant {
name: string;
category: string;
}
interface IPlant{
name: string;
genus: string;
category: string;
}
function identity(arg: any) {
return arg;
}
var output1 = identity('hello') // output is string
var output2 = identity(123) // output is number
function identity<T>(arg: T): T {
return arg;
}
var output1 = identity<string>('hello') // type of output is string
var output2 = identity(123) // type of output is number
var output3 = identity<boolean>(true) // type of output is boolean
Here, we’ll create an interface that has a single .length property and then we’ll use this interface and the extends keyword to denote our constraint:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
Occasionally, you’ll run into a library that expects a parameter to be either a number or a string. For instance, take the following function:
function padLeft(value: string, padding: string | number) {
// ...
}
// errors during compilation
let indentedString = padLeft("Hello world", true);
type LinkedList<T> = T & { next: LinkedList<T> };
interface Person {
name: string;
}
var people: LinkedList<Person>;
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;
Intersection types are closely related to union types, but they are used very differently.
type Easing = "ease-in" | "ease-out" | "ease-in-out";
class UIElement {
animate(dx: number, dy: number, easing: Easing) {
if (easing === "ease-in") {
// ...
}
else if (easing === "ease-out") {
}
else if (easing === "ease-in-out") {
}
else {
// error! should not pass null or undefined.
}
}
}
let button = new UIElement();
button.animate(0, 0, "ease-in");
button.animate(0, 0, "uneasy"); // error: "uneasy" is not allowed here
String literal types allow you to specify the exact value a string must have.
declare class Tether {
constructor(options: Tether.ITetherOptions);
public setOptions(options: Tether.ITetherOptions): void;
public enable(): void;
public static position(): void;
}
declare namespace Tether {
interface ITetherOptions {
classes?: {[className: string]: boolean};
classPrefix?: string;
constraints?: ITetherConstraint[];
element?: HTMLElement | string | any /* JQuery */;
}
interface ITetherConstraint {
attachment?: string;
pin?: boolean | string[];
to?: string | HTMLElement | number[];
}
}
declare module "tether" {
export = Tether;
}
let x = 3; // The type of the x variable is inferred to be number.
function createZoo(): Animal[] {
return [new Rhino(), new Elephant(), new Snake()];
}
let zoo = createZoo(); // It is Animal[]
function echo<T>(value: T) {
return value;
}
let numb = echo<number>(2); // numb is number
let text = echo('Some'); // text is string
var items = getItems();
var goSportsTeam = true;
var letter = 'z';
some-javascript.js
some-typescript.ts
enum CardSuit {
Clubs,
Diamonds,
Hearts,
Spades
}
// Sample usage
var card = CardSuit.Clubs;
switch (myCard.suit) {
case CardSuit.Clubs:
console.log(CardSuit.Clubs);
break;
otherwise:
console.log('Not a club.');
}
namespace my.example {
export function doSmth(){
// Actions
}
}
// Somewhere else
console.log(my.example.doSmth())
// ES2015
doSomething (smidge) {
if (smidge instanceOf repo
&& smidge.myProp) {
let a = smidge.myProp;
}
//...
}
// Transpiled ES5
function doSomething (smidge) {
if (smidge instanceOf repo
&& smidge.myProp) {
var a = smidge.myProp;
}
//...
}
// TypeScript
doSomething (smidge:repo) {
let a = smidge.myProp;
...
}
// Transpiled ES5
function doSomething (smidge) {
var a = smidge.myProp;
...
}
function Troll() {}
Object.defineProperty(Troll.prototype, "message", {
get: function () {
return "You mad bro?";
},
set: function (msg) {
console.log("Cool message bro ...");
}
});
class Troll {
get message() {
return "You mad bro?";
}
set message(msg) {
console.log("Cool message bro ...");
}
}
var Troll = (function () {
function Troll() {
}
Object.defineProperty(Troll.prototype, "message", {
get: function () {
return "You mad bro?";
},
set: function (msg) {
console.log("Cool message bro ...");
},
enumerable: true,
configurable: true
});
return Troll;
})();
function DoSomethingCool() {
// no ...
}
function DoSomethingCool() {
// no ...
}
function DoSomethingCool() {
// no ...
}
function Fetcher () {};
Fetcher.prototype.massageIt = function (data) {
return data;
};
Fetcher.prototype.fetchStuff = function () {
var _this = this;
return getJSON("/stuff").then(function (data) {
return _this.massageIt(data.data);
});
};
function Fetcher () {}
Fetcher.prototype.massageIt = function (data) {
return data;
};
Fetcher.prototype.fetchStuff = function () {
return getJSON("/stuff").then((data) => {
return this.massageIt(data.data);
});
};
function Fetcher() {
}
Fetcher.prototype.massageIt = function (data) {
return data;
};
Fetcher.prototype.fetchStuff = function () {
var _this = this;
return getJSON("/stuff").then(function (data) {
return _this.massageIt(data.data);
});
};
function Say(words) {
if (typeof words === 'undefined') {
words = "Hello World";
}
console.log(words);
}
function Say(words = "Hello World") {
console.log(words);
}
function Say(words) {
if (words === void 0) { words = "Hello World"; }
console.log(words);
}
function Add(/* ...values */) {
var slice = Array.prototype.slice,
values = slice.call(arguments);
return values.reduce(function (sum, value) {
return sum + value;
});
}
function Add(...values) {
return values.reduce((sum, value) => sum + value);
}
function Add() {
var values = [];
for (var _i = 0; _i < arguments.length; _i++) {
values[_i - 0] = arguments[_i];
}
return values.reduce(function (sum, value) {
return sum + value;
});
}
var name = "Dima",
age = 23;
console.log("My name is " + name + ". I'm " +
age + " years old")
var name = "Dima";
var age = 23;
var isFree = true;
console.log(`My name is ${name}. I'm ${age} years old
and I'm ${isFree ? '' : 'not'} free`);
var name = "Dima";
var age = 23;
var isFree = true;
console.log("My name is " + name + ". I'm " + age
+ " years old \n and I'm "
+ (isFree ? '' : 'not') + " free");
var MyModule = MyModule || {};
MyModule.Foo = "Bar";
MyModule.LogFoo = function () {
console.log(MyModule.Foo);
};
namespace my.example {
export function doSmth(){
// Actions
}
}
var my;
(function (my) {
var example;
(function (example) {
function doSmth() {
// Actions
}
example.doSmth = doSmth;
})(example = my.example || (my.example = {}));
})(my || (my = {}));
// Somewhere else
console.log(my.example.doSmth());
# INSTALL
npm install -g typescript
#COMPILE
tsc helloworld.ts
{
"compilerOptions": {
"jsx": "react",
"module": "commonjs",
"noEmitOnError": true,
"outDir": "./dist/",
"removeComments": true,
"allowJs": true
},
"files": [
"./index.ts" // Entry point
]
}
alm.tools
Atom
Eclipse
Emacs
NetBeans
Sublime Text
Vim
Visual Studio
Visual Studio Code
WebStorm
# Install Typings CLI utility.
npm install typings --global
# Install i.e. React.js
typings install --save --ambient react
# If you use the package as a module:
# Install non-ambient typings
typings install chai --save
# If you use the package through script tag, or
# it is part of the environment, or
# the non-ambient typings is not yet available:
# Install ambient typings
typings install mocha --ambient --save
...
module: {
loaders: [{
test: /\.tsx?$/,
loader: 'awesome-typescript',
include: [path.resolve(path.join(__dirname, "src"))],
query: {
doTypeCheck: true,
useCache: true,
forkChecker: true,
usePrecompiledFiles: true,
tsconfig: './src/tsconfig.json',
cacheDirectory: __dirname + '/.awcache'
}
}]
}
...
Matured technology
Well supported
'JavaScript safe'
Must have in every project
http://www.typescriptlang.org - TypeScript
http://www.typescriptlang.org/play/index.html - Sandbox
https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md - TypeScript Language Specification
https://www.gitbook.com/book/basarat/typescript - TypeScript Deep Dive
https://www.youtube.com/watch?v=r_yBvQxEbFg - Введение в TypeScript
https://www.youtube.com/watch?v=_3n4JdZdXWo - Разработка на TypeScript
https://github.com/s-panferov/awesome-typescript-loader - Loader for webpack