TypeScript en 20 mn
Loïc Mathieu - @loicmathieu
Introduction
Introduction
- Langage créé par Anders Hejlsberg en 2012
- Projet open-source maintenu par Microsoft (Version actuelle 3.2)
- Propose une extension du JavaScript apportant le typage
- Influencé par JavaScript, Java et C#
Introduction
- Phase de compilation nécessaire pour générer du JavaScript
- Ajout de nouvelles fonctionnalités au langage JavaScript
- Rétrocompatible: Tout programme JavaScript est un programme TypeScript
Principales fonctionalités
- Typage et inférence de type
- Enum, Tuples...
- Classes / Interfaces / Héritage
- Génériques
- Les fichiers de définitions
- Décorateurs
Le compilateur
-
TypeScript se présente sous la forme d'un paquet NPM
-
Le paquet contient un CLI qui permet d'utiliser le compilateur : tsc
- Toutes les options de compilation sont accessibles via le CLI
- Le plus souvent, on utilisera un fichier de configuration tsconfig.json
npm install --global typescript
Le Typage
Les variables
var variableName: VariableType = value;
let variableName2: VariableType = value;
const variableName3: VariableType = value;
Et en JS ?
//the type
const Model = use('Model')
//the variable
const Item = use('App/Item/Models/Item')
//what should be ...
assert.isTrue(Item.prototype instanceof Model)
Les types primitifs
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;
}
undefined et !
unknow (3.0)
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
}
Les fonctions
//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, ...
Les paramètres optionnels
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 :
- Utilisation du caractère ? avant le type
- L'ordre de définition est très important
- Aucune implication dans le code JavaScript généré
- S'il n'est pas défini, le paramètre aura la valeur undefined
Spécialisation de fonction
function fn(param: string): number;
function fn(param: number): string;
function fn(param: any): any {
if (typeof param === "number") {
return "string";
} else {
return 42;
}
}
Array
//litteral
const list: number[] = [1, 2, 3];
//Array
const list: Array<number> = [1, 2, 3];
Tuple
const tuple: [string, number] = ['Zenika', 10];
const [name, age] = tuple;
Enum
//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
Et en JS ?
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'
}
Inférence de type
Basé sur :
- Les types de données à l'initialisation des variables
- Les valeurs par défaut des arguments de fonctions
- Le type de données retourné dans une fonction
Duck typing :
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
Classes
Classes
Se base sur les classes de ES2015 et les enrichit
class Person {
constructor(
firstName: string,
lastName: string = "Dupont"
)
}
const person: Person = new Person("Michel");
Méthode
class Person {
sayHello(message: string): void {
console.log(`Hello ${message}`);
}
}
const person: Person = new Person();
person.sayHello('World'); //-> 'Hello World'
Propriété
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'
Modificateur de visibilité
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'.
- public (le défaut)
- protected
- private
- readonly
statique
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'
héritage (ES2015)
class Person {
constructor() {}
speak() {}
}
class Child extends Person {
constructor() { super(); }
speak() { super.speak(); }
}
interface
//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}`);
}
Et en JS ?
//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}`);
}
}
Generics
Generics
//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'.
Generics
//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'.
Merci !
&
Question ?
Loïc Mathieu - @loicmathieu
TypeScript en 20 mn
By loicmathieu
TypeScript en 20 mn
- 604