Loïc Mathieu - @loicmathieu
TypeScript se présente sous la forme d'un paquet NPM
Le paquet contient un CLI qui permet d'utiliser le compilateur : tsc
npm install --global typescript
var variableName: VariableType = value;
let variableName2: VariableType = value;
const variableName3: VariableType = value;
//the type
const Model = use('Model')
//the variable
const Item = use('App/Item/Models/Item')
//what should be ...
assert.isTrue(Item.prototype instanceof Model)
const isDone: boolean = false;
const height: number = 6;
const phone_number: number = 555_734_2231;
const milion: number = 1_000_000;
const name: string = 'Carl';
const names: string[] = ['Carl', 'Laurent'];
const notSure: any = 4;
const alsoNotSure = 5; //-> implicit number
let x!: number;
initialize();
// erreur sans le !
console.log(x + x);
function initialize() {
x = 10;
}
function f21<T>(pAny: any, pNever: never, pT: T) {
let x: unknown;
x = 123;
x = new Error();
x = x;
x = pAny;
x = pNever;
x = pT;
}
function f22(x: unknown) {
let v1: any = x;
let v2: unknown = x;
let v3: object = x; // Error
let v4: number = x; // Error
let v6: {} = x; // Error
let v7: {} | null | undefined = x; // Error
}
//regular fonction
function namedFunction(arg1: string, arg2: number): string {
return `${arg1} - ${arg2}`;
}
//arrow fonction
let myFunc: (arg1: string, arg2: number) => string;
//new 3.0 with safe typings
type Function<A extends any[], R> = (...args: A) => R;
Supporte : param par défaut, rest parameters, décomposition, ...
function fn(name: string, surname?: string): void {
console.log(name, surname);
}
fn(); //-> compilation error
fn('carl'); //-> 'carl' undefined
fn('carl', 'boss'); //-> 'carl' 'boss'
Un paramètre peut être optionnel :
function fn(param: string): number;
function fn(param: number): string;
function fn(param: any): any {
if (typeof param === "number") {
return "string";
} else {
return 42;
}
}
//litteral
const list: number[] = [1, 2, 3];
//Array
const list: Array<number> = [1, 2, 3];
const tuple: [string, number] = ['Zenika', 10];
const [name, age] = tuple;
//with default index
enum Music { Rock, Jazz, Blues };
const c: Music = Music.Jazz;
//with defined index
enum Music { Rock = 2, Jazz = 4, Blues = 8 };
const c: Music = Music.Jazz;
//getting the name of the enum
const style: string = Music[Music.Jazz]; //Jazz
const MappingType = {
/*
default type : will be mapped as following :
'boolean:boolean', 'integer:long', 'number:double', 'object:object', 'string:text'
array will not be mapped to a type as it's not needed for elasticsearch
*/
DEFAULT: 'default',
// no mapping will be created for this field and the field will not be included in the index
NOT_SEARCHABLE: 'not_searchable',
// the field will be included in the index but not analyzed : match only on the full value (type='keyword')
NOT_ANALYZED: 'not_analyzed'
}
Basé sur :
Si je vois un oiseau qui vole comme un canard, cancane comme un canard, et nage comme un canard, alors j'appelle cet oiseau un canard
Se base sur les classes de ES2015 et les enrichit
class Person {
constructor(
firstName: string,
lastName: string = "Dupont"
)
}
const person: Person = new Person("Michel");
class Person {
sayHello(message: string): void {
console.log(`Hello ${message}`);
}
}
const person: Person = new Person();
person.sayHello('World'); //-> 'Hello World'
Définit dans le corps de la classe,
se comporte comme un let
class Person {
firstName: string;
lastName: string = "Dupont";
age: number;
hobbies: string[];
}
const person: Person = new Person();
console.log(person.lastName); //-> 'Dupont'
class Person {
private message: string = 'World';
public sayHello(): void {
console.log(`Hello ${this.message}`);
}
}
const person: Person = new Person();
person.sayHello(); //-> 'Hello World'
console.log(person.message); // compilation error
// Property 'message' is private and only accessible
// within class 'Person'.
class Person {
static message: string = 'World';
static sayHello(): void {
console.log(`Hello ${Person.message}`);
}
}
const person: Person = new Person();
Person.sayHello(); //-> 'Hello World'
console.log(Person.message); // -> 'World'
person.sayHello(); // compilation error
// Property 'sayHello' does not exist on type 'Person'
class Person {
constructor() {}
speak() {}
}
class Child extends Person {
constructor() { super(); }
speak() { super.speak(); }
}
//class interface
interface Person {
sayHello(message: string): void;
}
class Adult implements Person {
sayHello(message: string): void {
console.log(`Hello ${message}`);
}
}
//fonction interface
interface SayHello {
(message: string): string;
}
let sayHello: SayHello;
sayHello = function(source: string): string {
return source.toLowerCase();
}
//parameter (object) interface
interface Message {
message: string
title?: string
}
function sayHello(options: Message) {
console.log(`Hello ${options.message}`);
}
//class interface
class Person {
constructor(){
if(sayHello == undefined){
throw new TypeDefError("sayHello is not implemented");
}
}
}
class Adult extends Person {
this.sayHello(message) {
console.log(`Hello ${message}`);
}
}
//on function
function identity<T>(arg: T): T {
return arg;
}
identity(5).toFixed(2); //-> '5.00'
identity(true); //-> true
identity('hello').toFixed(2); // compilation error :
// Property 'toFixed' does not exist on type '"hello"'.
//on class
class Log<T> {
log(value: T) {
console.log(value);
}
}
const numericLog = new Log<number>();
numericLog.log(5); //-> 5
numericLog.log('hello'); // compilation error
// Argument of type '"hello"' is not assignable to parameter of type 'number'.
//on interface
interface transform<T, U> {
transform : (value:T) => U;
}
class NumberToStringTransform implements transform<number, string> {
transform(value: number): string {
return value.toString();
}
}
const numberTransform = new NumberToStringTransform();
numberTransform.transform(3).toLowerCase(); //-> '3'
numberTransform.transform(3).toFixed(2); // compilation error
// Property 'toFixed' does not exist on type 'string'.
&
Loïc Mathieu - @loicmathieu