Advanced Typescript
Typescript

Types primitifs

Variables, déclaration et inférence de type

Déclarer une variable simple

let counter = 10;
let counter: number

Comme on peut le constater TypeScript est capable d'inférer le type de counter qui est un number.

Si l'on essaie d'assigner une valeur avec un autre type que number on se retrouve alors avec une erreur TypeScript.

let  = 10;
counter = 'dix';
Type 'string' is not assignable to type 'number'.

En typescript les types sont définit lorsqu'une valeur est assignée à cette variable.

Utilisation de const et types littéraux

Essayons la même chose avec const :

const humidity = 79;
const humidity: 79

On remarque que le type de cette variable n'est pas number, mais 79. TypeScript fait ici une inférence plus spécifique, car :

  • une variable déclarée avec const ne peut pas être réassignée
  • la valeur initiale assignée à humidity est un nombre, qui est immuable

Ainsi, humidity sera toujours égal à 79 dans ce programme.

Types littéraux

Les types comme 79 sont appelés des types littéraux — cela signifie que « seul 79 est autorisé ».

💡 Inférence non intrusive

TypeScript n'infère pas de façon trop spécifique pour ne pas gêner le comportement courant. Par exemple, la déclaration avec let ci-dessus aurait pu être de type 79, mais cela aurait empêché de réassigner la variable à 7 ou 8.

Un type comme ensemble de valeurs

On peut voir un type comme un ensemble de valeurs autorisées. Par exemple :

{ 1, 2, 3 } // "1 ou 2 ou 3"

Regardons nos exemples :

let temperature = 19;
let temperature: number
const humidity = 79;
const humidity: 79

Le type number de temperature représente l'ensemble « tous les nombres possibles ». On peut réassigner une nouvelle valeur numérique à temperature :

let  = 19;
 = 23;

Le type 79 de humidity représente l'ensemble « seul 79 est autorisé », donc seule cette valeur est autorisée:

Inférence avec as const

On peut forcer une variable déclarée avec let à avoir le même type qu'un const :

let  = 19;
let humidity = 79 as ;
let humidity: 79

On retrouve les mêmes types, mais la réassignabilité change. Essayons quelques affectations :

let  = 19;
let  = 79 as ;
 = 23; // (1) OK
 = ; // (2) OK
humidity = ; // (3) ❌ ERROR
Type 'number' is not assignable to type '79'.
= 79; // (4) OK humidity = 78; // (5) ❌ ERROR
Type '78' is not assignable to type '79'.

Chaque affectation implique une vérification d'équivalence de type : « le type de y est-il compatible avec le type de x ? ».

Le type any et l'annotation de type

Parfois, on déclare une variable avant de l'initialiser :

const  = .(.() * 500) + 500;
let  = new ();
let endTime;
let endTime: any
(() => { = 0; = new (); }, );

Ici, endTime est initialisé sans type, donc il devient implicitement any. Si on veut plus de sécurité, on peut annoter le type :

let : Date;
(() => {
  endTime = 0;
Type 'number' is not assignable to type 'Date'.
= new (); }, RANDOM_WAIT_TIME);

Casting de type

On peut parfois vouloir forcer le compilateur à considérer une valeur comme un type particulier :

let  = new ("Jan 1, 2012");
let  = ;
let  =  as any; // force le type à `any`

C'est à utiliser avec précaution. Il est parfois sûr de caster vers un type plus général, mais dangereux vers un type plus spécifique ou non lié :

const  = 79 as number; // est-ce que 79 est un nombre ? Oui, donc c'est sûr
let  = "oops" as any as Date;
.(); // 💥 Erreur à l'exécution

TypeScript n'autorise pas le cast direct de string vers Date :

let  = "oops" as Date;
Conversion of type 'string' to type 'Date' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.

Arguments et valeurs de retour de fonction

La syntaxe : Date vue plus haut s'applique aussi aux arguments et valeurs de retour de fonction :

function (a, b) {
Parameter 'b' implicitly has an 'any' type.
Parameter 'a' implicitly has an 'any' type.
return + // chaînes ? nombres ? un mélange ? } const = (3, "4");

Sans annotation, tout est permis :

function (: any, : any): any {
  return  + ;
}
const  = (3, "4");

Mais cela peut poser problème :

const  = add(3, "4");
const  = new (); // Erreur potentielle

Ajoutons des annotations de type :

function (: number, : number) {
  return  + ;
}
const  = (3, "4");
Argument of type 'string' is not assignable to parameter of type 'number'.

On peut aussi annoter le type de retour :

function (: number, : number): number {}
A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.

Une fois le corps de la fonction implémenté, l'erreur disparaît :

function (: number, : number): number {
  return  + ;
}