by Carl Vuorinen / @cvuorinen
Is a representation of real-world concepts,
not just software components
is not just an UML diagram
... but sure it's helpful to draw it out
An approach to software development
for complex needs by connecting the
implementation to an evolving model
A language used to describe the domain
both in conversation and in code
Helps design systems for:
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. typescriptlang.org
npm install typescript --save
tsc src/*.ts
npm install --save @types/lodash
Older versions need to download definitions separately,
with Typings (or manually)
npm install typings --global
typings install lodash --save
function add(a: number, b: number): number {
return a + b;
}
add(2, 3); // 5
add(2, '4'); // Error: Type 'string' is not assignable to type 'number'
let color: string = 'red';
color = add(4, 2); // Error: Type 'number' is not assignable to type 'string'
interface Item {
id: number;
name: string;
categories?: string[];
}
const item: Item = { id: 1, name: 'MyItem' }; // OK
const item2: Item = { id: 2, name: 12345 }; // Error
// Type '{ id: number; name: number; }' is not assignable to type 'Item'.
// Types of property 'name' are incompatible.
// Type 'number' is not assignable to type 'string'.
Array<string>
class Group {
private name: string;
constructor(name: string) {
this.name = name;
}
public greet(): string {
return `Hello ${this.name}`;
}
}
const ngFinland = new Group('Angular Finland');
ngFinland.greet(); // Hello Angular Finland
Using a rich type system to create
readable code and easily understandable APIs
define custom types
for any valid type definition
type AccountNumber = string;
type Money = number;
type Uuid = string;
type TransactionId = Uuid;
interface Transaction {
create: (amount: Money, from: AccountNumber, to: AccountNumber) => TransactionId;
}
type Position = 'static';
type Enabled = 1;
type Disabled = 0;
type Something = string | number | boolean;
type Status = Enabled | Disabled;
type Currency = 'EUR' | 'USD' | 'BTC';
type Money = [number, Currency];
const price: Money = [25, 'EUR'];
const price2: Money = [74.8, 'USD'];
price[0]; // 25
price[1]; // 'EUR'
const [amount, currency] = price;
function add(a: Money, b: Money): Money {
if (a[1] !== b[1]) {
throw 'Cannot add different currencies';
}
return [
a[0] + b[0],
a[1]
];
}
add(price, price2); // Error 'Cannot add two different currencies'
add(price, [17.5, 'EUR']); // [ 42.5, 'EUR' ]
type Translation = string;
type TranslationList = { [id: string]: Translation };
const finnishTranslations: TranslationList = {
'Hello': 'Moi',
'Angular': 'Kulmikas',
'Finland': 'Suomi'
};
import Observable from "rx";
type Translation = string;
type Language = "en" | "fi" | "se";
type TranslationList = { [id: string]: Translation };
type Translations = [Language, TranslationList];
type TranslationStream = Observable<Translation>;
interface Translator {
addTranslations: (Translations) => void;
selectLanguage: (Language) => void;
translate: (key: string) => Translation;
translateAsync: (key: string) => TranslationStream;
}
enum Direction { North, East, South, West };
enum Status { Disabled = 0, Enabled = 1 };
interface Item {
id: number;
status: Status;
// ...
}
const items: Item[] = [
{ id: 1, status: Status.Enabled },
{ id: 2, status: Status.Disabled }
];
const enabledItems = items.filter(item => item.status === Status.Enabled);
const item1 = items[0];
Status[item1.status]; // 'Enabled'
enum Suit { Club, Diamond, Spade, Heart };
enum Rank { Two = 2, Three, Four, Five, Six, Seven, Eight,
Nine, Ten, Jack, Queen, King, Ace };
type Card = [Suit, Rank];
type Hand = Card[];
type Deck = Card[];
type Deal = (Deck) => [Card, Deck];
type PickupCard = (Hand, Card) => Hand;
class Uuid {
constructor(private value: string) {
if (!/^[-a-fA-F\d]{36}$/.test(value)) {
throw `Invalid UUID: "${value}"`;
}
}
public toString(): string {
return this.value;
}
public static create(): Uuid {
return new Uuid(
// generate UUID
);
}
}
const id = new Uuid('bbd0ed2d-98e9-11e6-a49f-1633bb132a9c');
const newId = Uuid.create(); // generated id e.g. '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
const invalid = new Uuid('foo'); // Error: Invalid UUID: "foo"
When you got a rich type system coupled with a compiler,
it gives you confidence
You need less unit tests
You may not always trust your coworkers
(...or yourself few months from now)
But you can trust the compiler
Dynamic typing: the belief that you can’t explain to a computer why your code works but you can keep track of it all in your head. Robert C.Martin
but you can get started by making things
more explicit a little bit at a time