is valid TypeScript) • Provides features from upcoming ECMAScript standards versions • Adds optional strict typing • Adopted by a number of projects, Angular 2 prominently • Microsoft • http://www.typescriptlang.org
have not worked extensively with statically typed languages • You are familiar with the build pipeline tools appropriate to your projects or environment (or are willing to talk after the session)
than weak typing, and […] static typing is also somewhat better than dynamic typing. Ray, B., Posnett, D., Filkov, V., Devanbu, P. T. (2014). A Large Scale Study of Programming Languages and Code Quality in Github
console.log(div("a", "b")); function div(a, b) { return a / b; } console.log(div("a", "b")); //# sourceMappingURL=typed.js.map ⊗ > $ tsc examples/typed.ts examples/typed.ts(5,17): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
my IDE (I’m looking at you, JetBrains) • Slightly more verbose code is more explicit and I believe in explicit > implicit • Allows the potential for fewer tedious tests. But testing is still vital.
{ return a + b; } let foo = 42; let bar = "fred"; console.log(combine(foo, bar)); function combine(a:any, b:any):any { return a + b; } let foo:number = 42; let bar:string = "fred"; console.log(combine(foo, bar));
string!"; let stringLength: number = <string>anyValue.length; // angle bracket style let stringLength: number = (anyValue as string).length; // JSX-style
isGame:true, sourceAnimal: "deer", gameiness: 3 }; cookMeat(venison); console.log(venison.isCooked); examples/recipes/meat.ts(23,5): error TS2322: Type '{ isCooked: boolean; isGame: boolean; sourceAnimal: string; gameiness: number; }' is not assignable to type 'Meat'. Object literal may only specify known properties, and 'gameiness' does not exist in type 'Meat'.
number, unit: string } interface RecipeDictionary { [index: string]: Ingredient name: string; } > $ tsc examples/dictionary.ts examples/dictionary.ts(9,5): error TS2411: Property 'name' of type 'string' is not assignable to string index type 'Ingredient'.
properties come from a linked object (the prototype) • The prototype model can be used to implement classical inheritance • ES6 (and TypeScript) introduce a “class” keyword that provides syntactic sugar for creating classical inheritance chains using prototypes
class Ingredient { public name:string; public unit:string; public quantity:number; } == • Public properties are visible to any caller • Protected properties are visible to a class instance and its children • Private properties are visible only to a class instance
{ this._name = name; } } class Butter extends Ingredient { constructor() { super(“Butter"); } } class Condiment { private _name:string; constructor(name:string) { this._name = name; } } let ingredients:Ingredient[] = [new Butter(), new Condiment("Ketchup")]; > $ tsc examples/classes/private.ts examples/classes/private.ts(23,5): error TS2322: Type '(Butter | Condiment)[]' is not assignable to type 'Ingredient[]'. Type 'Butter | Condiment' is not assignable to type 'Ingredient'. Type 'Condiment' is not assignable to type 'Ingredient'. Types have separate declarations of a private property '_name'.
TS2445: Property '_unit' is protected and only accessible within class 'Ingredient' and its subclasses. class Ingredient { private _name:string; protected _unit:string; constructor(name:string) { this._name = name; } } class Butter extends Ingredient { constructor() { super("Butter"); this._unit = "tbsp"; } } let butter= new Ingredient("butter"); butter.unit = "cup";
anonymousAdd = function (a:number, b:number): number { return a+b; }; // reference parameter list return type definition let fullAdd: (a:number, b:number) => number = function (a:number, b:number): number { return a+b; };
ingredients:Ingredient[]; } function createIngredientList(...ingredients:Ingredient[]): IngredientList { let list = { ingredients:[] }; for (let ingredient of ingredients) { list.ingredients.push(ingredient); } return list; }
cook(ingredients:IngredientList, skillet:Skillet): SkilletMeal; function cook(ingredients:IngredientList, cookingAppliance:any, ...options:Array<any>): Meal { if (typeof cookingAppliance === "Skillet") { return new SkilletMeal(ingredients); } else if (typeof cookingAppliance === "Crockpot") { return new CrockpotMeal(ingredients, options[0], options[1]); } } let skillet = cook(new IngredientList(), new Skillet()); let crockpost = cook(new IngredientList(), new Crockpot(), 225, 360); let dutchoven = cook(new DutchOven()); > $ tsc examples/functions/overload.ts examples/functions/overload.ts(19,17): error TS2346: Supplied parameters do not match any signature of call target.
let meatRecipe = new Recipe<MeatIngredient>(); meatRecipe.add(new MeatIngredient()); let veganRecipe = new Recipe<VeganIngredient>(); veganRecipe.add(new VeganIngredient()); veganRecipe.add(new MeatIngredient()); // error
} } let badRecipe = new Recipe<BadIngredient>(); badRecipe.add(new BadIngredient()); > $ tsc examples/generics/generics.ts examples/generics/generics.ts(51,28): error TS2344: Type 'BadIngredient' does not satisfy the constraint 'Ingredient'.
if (animal.scale) { animal.scale(); } return animal.fillet(); } > $ tsc examples/unions.ts examples/unions.ts(13,16): error TS2339: Property 'pluck' does not exist on type 'Chicken | Fish'. examples/unions.ts(14,16): error TS2339: Property 'pluck' does not exist on type 'Chicken | Fish'. examples/unions.ts(16,16): error TS2339: Property 'scale' does not exist on type 'Chicken | Fish'. examples/unions.ts(17,16): error TS2339: Property 'scale' does not exist on type 'Chicken | Fish'.