TypeScript

The Good Parts

by Jeremy Mason


Contact me

@jeremyalan
jeremyalan@gmail.com

Sponsors

Quick Poll

What is TypeScript?

TypeScript is a programming language
(Full spec available at typescriptlang.org)

Superset of Javascript
(pure JS is valid TypeScript)

Transcompiles into pure Javascript

What is TypeScript

Offers other language features

  • Modules (Namespaces)
  • Types + inheritance
  • Inline functions
  • many more...

What isn't TypeScript

C++ | C# | Java

Transcompiling to Javascript from existing languages is difficult because they have different design principles

TypeScript is a whole new language designed to harness the implicit power of Javascript

What isn't TypeScript

CoffeeScript

CoffeeScript provides a way to be more expressive
In other words, do more with less code

TypeScript is more verbose but provides type safety

What isn't TypeScript

Backbone, Knockout, Angular, ...

TypeScript is just a language
It's not a framework for building applications

It is possible to build web applications with TypeScript using any existing framework

Classes

Simple example

class Person {
 FirstName: string;
 LastName: string;
 
 constructor(firstName: string, lastName: string) {
  this.FirstName = firstName;
  this.LastName = lastName;
 }
 
 getFullName() {
  return this.FirstName + ' ' + this.LastName;
 }
}
...

var person = new Person('Tom', 'Smith');

console.log(person.getFullName()); // 'Tom Smith'

Classes

Private variables

class Person {
 private FirstName: string;
 private LastName: string;
 
 constructor(firstName: string, lastName: string) {
  this.FirstName = firstName;
  this.LastName = lastName;
 }
 
 getFullName() {
  return this.FirstName + ' ' + this.LastName;
 }
}

var person = new Person('Tom', 'Smith');

// OK
console.log(person.getFullName());

// ERROR!!
console.log(person.FirstName);	

Classes

Private variables


A brief note on using private

Javascript does not understand public/private. Private scope is only enforced by the TypeScript compiler

Classes

Static variables

class Logger {
 static Instance = new Logger();
 
 constructor() {
 }
 
 write(message: string) {
  console.log(message);
 }
}

// Sample usage
Logger.Instance.write('Hello, world!');

Classes

Inheritance

class Employee extends Person {
 Title: string;
 
 constructor(first: string, last: string, title: string) {
  super(first, last);
  
  this.Title = title;
 }
 
 getFullName() {
  return super.getFullName() + ', ' + this.Title;
 }
}
...

var employee = new Employee('Tom', 'Smith', 'VP of Engineering');

// 'Tom Smith, VP of Engineering'
console.log(employee.getFullName());

Interfaces

Simple example

interface IPerson {
 FirstName: string;
 LastName: string;
 
 getFullName: () => string;
}

class Person implements IPerson {
 FirstName: string;
 LastName: string;
 
 constructor(firstName: string, lastName: string) {
  this.FirstName = firstName;
  this.LastName = lastName;
 }
 
 getFullName() {
  return this.FirstName + ' ' + this.LastName;
 }
}

Interfaces

3rd Party Libraries

declare var $: (selector: string) => any;

interface JQuerySpin {
 spin: () => void;
}

(<JQuerySpin>$('#spinner')).spin();

Interfaces

3rd Party Libraries


A brief note on 3rd party interfaces

Interface definitions files end in .d.ts, meaning it is only used by the compiler (no compiled output).

DefinitelyTyped is a project on GitHub that provides interface definitions for common libraries.
https://github.com/borisyankov/DefinitelyTypedā€ˇ

Interfaces

Method overloading

Supported by interfaces, not by classes
interface Greeter {
 sayHello(): void;
 sayHello(name: string): void;
}

class ConsoleGreeter implements Greeter {
 sayHello(name) {
  if (name) {
   console.log('Hello, ' + name + '!');
  }
  else {
   console.log('Hey you!');
  }
  
 }
}

var greeter = new ConsoleGreeter();

greeter.sayHello();      // Hey you!
greeter.sayHello('Tom'); // Hello, Tom!

Type Annotations

Basic Types

  • number
  • string
  • Function
  • Custom Types (classes, interfaces, etc.)
  • Special type: any

Type Annotations

Basic Types

Variables
var x: string = 'Hello, world!';
Function arguments, return values
function sum(x: number, y: number): number {
 return x + y;
}
Function types
var sum: (x: number, y: number) => number;

sum = function (x, y) {
 return x + y;
}

Type Annotations

Lookup Types

TypeScript supports key/value maps

interface Person {
 Name: string;
}

var personsById: {
 [id: string]: Person;
}

var person = personsById['user'];

console.log(person.Name);

Functions

Default parameters

class Person {
 Name: string;
 Title: string;
 
 constructor(name: string, title: string = 'Mr.') {
  this.Name = name;
  this.Title = title;
 }
 
 getFullName() {
  return this.Title + ' ' + this.Name;
 }
}

var person1 = new Person('Tom Smith');
var person2 = new Person('Susie Johnson', 'Ms.');

console.log(person1.getFullName()); // 'Mr. Tom Smith'
console.log(person2.getFullName()); // 'Ms. Susie Johnson'

Functions

Splats

function format(fmt: string, ...args: any[]) {
 var result = fmt;
 
 for (var i = 0; i < args.length; i++) {
  result = result.replace('{' + i + '}', args[i]);
 }
 
 return result;
}

// Hello, Susie and Jim
console.log(format('Hello, {0} and {1}!', 'Susie', 'Jim'));

Functions

Inline Functions

(also called Lambda expressions)
var items = [
 { Name: 'Susie', Age: 27 },
 { Name: 'Jim', Age: 34 }
];

var result = _.find(items, a => a.Name == 'Jim');

// Multiple parameters
var sum = (a, b) => a + b;

// Multi-line
var abs = (a) => {
 if (a < 0) {
  return -a;
 }
 
 return a;
}

Functions

Inline functions

Inline functions will inherit 'this' context.
class Model {
 person: Person;
 
 theHardWay() {
  var that = this;
  
  $.ajax(...).done(function (data) {
   that.person = data;
  }
 }
 
 theEasyWay() {
  $.ajax(...).done(data => this.person = data);
 }
}

Modules

Simple example

module App.Views {
 export class MainView {
  private model: any;
  
  constructor(model) {
   this.model = model;
  }
  
  render() {
   ...
  }
 }
}

var model = {};
var view = App.Views.MainView(model);

view.render();

Modules

Public and Private Scope

module App.Views {
 class PrivateView {
 ...
 }
 
 export class PublicView {
 ...
 }
}

// OK
var public = new App.Views.PublicView();

// Error!
var private = new App.Views.PrivateView();

Modules

External References

/// <reference path="../../lib/jquery.d.ts" />

module App.Models {
 export class MainModel {
  data: any;
  
  init() {
  
   // $ is defined in jquery.d.ts
   
   $.ajax(...).done(data => this.data = data);
   
  }
 }
}

Tools

Web Playground

http://www.typescriptlang.org/Playground
  • Great for getting started
  • View compiler errors
  • Basic Intellisense support

Tools

Command-Line Compiler

  • Available via NPM
    > npm install -g typescript
  • Compile
    > tsc app.ts
  • File watcher also available
    > tsc -w

Tools

Other Plugins

  • Visual Studio 2012
    • TypeScript for VS2012
    • Web Essentials (VS2012)
  • WebMatrix
  • Sublime Text
  • Emacs
  • Vim
  • WebStorm (coming soon?)

Other Stuff

Source Maps

Allows you to debug TypeScript in
the browser using original source
  • Available via command-line
    > tsc --sourcemap app.ts
  • Browser support is limited, standard is emerging quickly

The Not So Good Parts

  • Tools and plugins are still clumsy
  • Lacks support for generics
  • Type annotations require more code
  • 3rd party integration is painful
    • DefinitelyTyped is great for common libraries!
    • Cast to <any> to go "unsafe"
    • Code generation?
  • Dynamic bindings, client templates are not strongly typed
    • AngularJS, Knockout
    • Mustache, Handlebars, Underscore

Questions


Thanks for listening!

Contact me

@jeremyalan
jeremyalan@gmail.com