TypeScript 4.0 Beta permet aux tuples d'accepter un nombre variable de param�tres,
et apporte l'inf�rence de propri�t� de classe des constructeurs

Types de tuple variadique (qui accepte un nombre variable de param�tres)

Consid�rez une fonction en JavaScript appel�e concat, qui prend deux types de tableau ou de tuple et les concat�ne ensemble comme un nouveau tableau.

Code JavaScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
function concat(arr1, arr2) {
    return [...arr1, ...arr2];
}

Consid�rez �galement tail, qui prend un tableau ou un tuple, et renvoie tous les �l�ments sauf le premier.

Code JavaScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
function tail(arg) {
    const [_, ...result] = arg;
    return result
}

Comment pourrions-nous taper l'un de ces �l�ments dans TypeScript?

Pour concat, la seule chose valable que nous pouvions faire dans les anciennes versions du langage �tait d'essayer d'�crire des surcharges. Une fonction surcharg�e est une fonction qui est d�finie plusieurs fois dans une application afin d�offrir diff�rentes logiques � l�application.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
function concat<>(arr1: [], arr2: []): [A];
function concat<A>(arr1: [A], arr2: []): [A];
function concat<A, B>(arr1: [A, B], arr2: []): [A, B];
function concat<A, B, C>(arr1: [A, B, C], arr2: []): [A, B, C];
function concat<A, B, C, D>(arr1: [A, B, C, D], arr2: []): [A, B, C, D];
function concat<A, B, C, D, E>(arr1: [A, B, C, D, E], arr2: []): [A, B, C, D, E];
function concat<A, B, C, D, E, F>(arr1: [A, B, C, D, E, F], arr2: []): [A, B, C, D, E, F];)

Ce qui nous donne donc sept surcharges lorsque le deuxi�me tableau est toujours vide. Ajoutons-en pour quand arr2 a un argument.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
function concat<A2>(arr1: [], arr2: [A2]): [A2];
function concat<A1, A2>(arr1: [A1], arr2: [A2]): [A1, A2];
function concat<A1, B1, A2>(arr1: [A1, B1], arr2: [A2]): [A1, B1, A2];
function concat<A1, B1, C1, A2>(arr1: [A1, B1, C1], arr2: [A2]): [A1, B1, C1, A2];
function concat<A1, B1, C1, D1, A2>(arr1: [A1, B1, C1, D1], arr2: [A2]): [A1, B1, C1, D1, A2];
function concat<A1, B1, C1, D1, E1, A2>(arr1: [A1, B1, C1, D1, E1], arr2: [A2]): [A1, B1, C1, D1, E1, A2];
function concat<A1, B1, C1, D1, E1, F1, A2>(arr1: [A1, B1, C1, D1, E1, F1], arr2: [A2]): [A1, B1, C1, D1, E1, F1, A2];

Il est donc clair que cela devient d�raisonnable. Malheureusement, vous vous retrouveriez �galement avec les m�mes types de probl�mes lors de la saisie d'une fonction comme tail.

C'est un autre cas de ce que l'�quipe TypeScript aime appeler � la mort par mille surcharges �, et cela ne r�sout m�me pas le probl�me en g�n�ral. Il ne donne que les types corrects pour autant de surcharges que nous voulons �crire. Si nous voulions cr�er un cas fourre-tout, nous aurions besoin d'une surcharge comme celle-ci:

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
function concat<T, U>(arr1: T[], arr2, U[]): Array<T | U>;

Mais cette signature n'encode rien � propos de la longueur de l'entr�e ou l'ordre des �l�ments lors de l'utilisation de tuples.

TypeScript 4.0 apporte deux changements fondamentaux, ainsi que des am�liorations d'inf�rence, pour rendre leur saisie possible.

Le premier changement est que les spreads (Spread ou REST param�tre est une technique qui peut �tre utilis�e dans le cas o� nous ne connaissons pas le nombre d'arguments qui sera envoy� � la fonction, un param�tre spread est d�not� par trois points (...) qui se placent devant le nom de param�tre) dans la syntaxe de type tuple peuvent d�sormais �tre g�n�riques. Cela signifie que nous pouvons repr�senter des op�rations d'ordre sup�rieur sur des tuples et des tableaux m�me lorsque nous ne connaissons pas les types r�els sur lesquels nous op�rons. Lorsque des spreads g�n�riques sont instanci�s (ou remplac�s par un type r�el) dans ces types de tuples, ils peuvent produire d'autres ensembles de types de tableau et de tuple.

Par exemple, cela signifie que nous pouvons taper une fonction comme queue, sans notre probl�me de �mort par mille surcharges�.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
function tail<T extends any[]>(arr: readonly [any, ...T]) {
    const [_ignored, ...rest] = arr;
    return rest;
}
 
const myTuple = [1, 2, 3, 4] as const;
const myArray = ["hello", "world"];
 
// type [2, 3, 4]
const r1 = tail(myTuple);
 
// type [2, 3, ...string[]]
const r2 = tail([...myTuple, ...myArray] as const);

Le deuxi�me changement est que les �l�ments spread peuvent appara�tre n'importe o� dans un tuple - pas seulement � la fin!

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
type Strings = [string, string];
type Numbers = [number, number];
 
// [string, string, number, number]
type StrStrNumNum = [...Strings, ...Numbers];

Auparavant, TypeScript g�n�rait une erreur comme celle-ci.

Citation Envoy� par TypeScript
A rest element must be last in a tuple type.
Mais maintenant, le langage peut aplanir les spreads � n'importe quelle position.

Lorsque nous r�partissons un type sans longueur connue, le type r�sultant devient �galement illimit� et tous les �l�ments cons�cutifs sont pris en compte dans le type d'�l�ment de repos r�sultant.

Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
type Strings = [string, string];
type Numbers = number[]
 
// [string, string, ...Array<number | boolean>]
type Unbounded = [...Strings, ...Numbers, boolean];
En combinant ces deux comportements ensemble, nous pouvons �crire une seule signature bien typ�e pour concat:

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
type Arr = readonly any[];
 
function concat<T extends Arr, U extends Arr>(arr1: T, arr2: U): [...T, ...U] {
    return [...arr1, ...arr2];
}

Bien que cette signature soit encore un peu longue, il ne s'agit toujours que d'une signature, elle ne doit �tre �crite qu'une seule fois, et elle donne en fait un comportement pr�visible sur tous les tableaux et tuples.

Si l'�quipe est plut�t satisfaite de cette fonctionnalit�, elle reconna�t qu'il existe �galement d'autres sc�narios plus sophistiqu�s. Par exemple, consid�rons une fonction pour appliquer partiellement des arguments appel�s partialCall.partialCall qui prend une fonction avec les quelques arguments initiaux attendus par cette fonction. Elle renvoie ensuite une nouvelle fonction qui prend tous les autres arguments dont la fonction a besoin et les appelle ensemble.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
function partialCall(f, ...headArgs) {
    return (...tailArgs) => f(...headArgs, ...tailArgs)
}

TypeScript 4.0 am�liore le processus d'inf�rence pour les param�tres de repos et les �l�ments de tuple de repos.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
type Arr = readonly unknown[];
 
function partialCall<T extends Arr, U extends Arr, R>(f: (...args: [...T, ...U]) => R, ...headArgs: T) {
    return (...b: U) => f(...headArgs, ...b)
}

Dans ce cas, partialCall comprend les param�tres qu'il peut et ne peut pas prendre initialement et renvoie des fonctions qui acceptent et rejettent de mani�re appropri�e tout ce qui reste.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const foo = (x: string, y: number, z: boolean) => {}
 
// This doesn't work because we're feeding in the wrong type for 'x'.
const f1 = partialCall(foo, 100);
//                          ~~~
// error! Argument of type 'number' is not assignable to parameter of type 'string'.
 
 
// This doesn't work because we're passing in too many arguments.
const f2 = partialCall(foo, "hello", 100, true, "oops")
//                                              ~~~~~~
// error! Expected 4 arguments, but got 5.
 
 
// This works! It has the type '(y: number, z: boolean) => void'
const f3 = partialCall(foo, "hello");
 
// What can we do with f3 now?
 
f3(123, true); // works!
 
f3();
// error! Expected 2 arguments, but got 0.
 
f3(123, "hello");
//      ~~~~~~~
// error! Argument of type '"hello"' is not assignable to parameter of type 'boolean'.

Nom : type.png
Affichages : 4551
Taille : 89,1 Ko

�l�ments de tuple �tiquet�s

Il est important d'am�liorer l'exp�rience des types de tuples et des listes de param�tres. L'id�e que nous pouvons utiliser des types de tuples pour les param�tres de repos devient cruciale. Par exemple, la fonction suivante qui utilise un type de tuple comme param�tre de repos�

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
function foo(...args: [string, number]): void {
    // ...
}

� Ne devrait pas diff�rer de la fonction suivante�

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
function foo(arg0: string, arg1: number): void {
    // ...
}

� Pour tout appelant de foo.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
foo("hello", 42); // works
 
foo("hello", 42, true); // error
foo("hello"); // error

Il y a un endroit o� les diff�rences commencent � devenir observables: la lisibilit�. Dans le premier exemple, nous n'avons aucun nom de param�tre pour les premier et deuxi�me �l�ments. Bien que ceux-ci n'aient aucun impact sur la v�rification de type, le manque d'�tiquettes sur les positions des tuples peut les rendre plus difficiles � utiliser - et il devient donc plus difficile de communiquer sur notre intention.

C�est pourquoi dans TypeScript 4.0, les types de tuples peuvent d�sormais fournir des �tiquettes.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
type Range = [start: number, end: number];

Poussant davantage la connexion entre les listes de param�tres et les types de tuples, l'�quipe a fait en sorte que la syntaxe des �l�ments de repos et des �l�ments facultatifs refl�te celle des listes de param�tres.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
type Foo = [first: number, second?: string, ...rest: any[]];

Lors de l'�tiquetage d'un �l�ment de tuple, tous les autres �l�ments du tuple doivent �galement �tre �tiquet�s.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
type Bar = [first: string, number];
//                         ~~~~~~
// error! Tuple members must all have names or all not have names.

Il convient de noter que les �tiquettes ne nous obligent pas � nommer nos variables diff�remment lors de la d�structuration. Ils sont purement l� pour la documentation et l'outillage.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
function foo(x: [first: string, second: number]) {
    // ...
 
    // note: we didn't need to name these 'first' and 'second'
    let [a, b] = x;
 
    // ...
}

Inf�rence de propri�t� de classe des constructeurs

TypeScript 4.0 peut d�sormais utiliser l'analyse de flux de contr�le pour d�terminer les types de propri�t�s dans les classes lorsque noImplicitAny est activ�.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
class Square {
    // Previously: implicit any!
    // Now: inferred to `number`!
    area;
    sideLength;
 
    constructor(sideLength: number) {
        this.sideLength = sideLength;
        this.area = sideLength ** 2;
    }
}

Dans les cas o� tous les chemins d'un constructeur ne sont pas attribu�s � un membre d'instance, la propri�t� est consid�r�e comme potentiellement undefined.

Code TypeScript : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Square {
    sideLength;
 
    constructor(sideLength: number) {
        if (Math.random()) {
            this.sideLength = sideLength;
        }
    }
 
    get area() {
        return this.sideLength ** 2;
        //     ~~~~~~~~~~~~~~~
        // error! Object is possibly 'undefined'.
    }
}

Source : billet TypeScript