13 votes

Dans Typescript, définissez le type d'un tableau dont le premier élément est plus spécifique que le reste.

Je voudrais définir un type pour un tableau dont le premier élément est un type spécifique (par exemple Function), et les autres éléments sont le type vide. Par exemple :

type FAs = [Function, {}, {}, {}, ...]; // pseudo code

Une telle chose est-elle possible ?

Le but est de fournir une fonction à argument unique comme celle-ci :

const myCaller = ([fun, ...args]: FAs) => fun.apply(args);

Une approche alternative serait d'utiliser deux arguments pour myCaller comme ceci :

const myCaller = (fun: Function, args: any[]) => fun.apply(args);

mais pour des raisons esthétiques, je préfère utiliser un seul argument. Je me demande également si le système de types supporte ce qui est sans doute un tuple de longueur arbitraire. Peut-être qu'une telle chose est indésirable pour des raisons informatiques que je ne comprends pas.

11voto

Si vous définissez

type FAs = [Function, {}];

Ensuite, les valeurs de type FAs nécessitera un premier élément de type Function un deuxième élément de type {} et les éléments successifs de Function | {} . C'est ainsi que les types de tableaux littéraux TypeScript fonctionnent. De la Docs TS :

Lorsqu'on accède à un élément en dehors de l'ensemble des indices connus, on utilise un type union à la place :

Cela devrait faire tout ce que vous voulez sauf pour le fait que vous pourrez passer dans un Function -comme troisième élément, etc. du tableau. Mais en fait, ce serait le cas de toute façon, puisque Function est compatible avec {} .

Il n'y a aucun moyen de contourner ce problème. Il n'y a pas de moyen dans TS de définir un type de tableau où le premier n Les éléments sont d'un ou de plusieurs types spécifiques, et il y a un nombre arbitraire d'éléments restants d'un autre type spécifique.

Je me demande également si le système de types supporte ce qui est sans doute un tuple de longueur arbitraire.

En fait, le système de type uniquement supporte les tuples de longueur arbitraire. Si vous dites

type Tuple = [number, number];

ce type est compatible avec tout tableau, de longueur deux ou plus qui contient des chiffres. Si vous dites

type Tuple = [string, number];

ce type est compatible avec tout tableau, de longueur deux ou plus qui a une chaîne de caractères comme premier élément, un nombre comme deuxième élément, et une chaîne de caractères ou un nombre comme troisième élément, etc. Je ne qualifierais pas les raisons de ce comportement de "basées sur l'informatique" ; il s'agit plutôt de ce qu'il est possible pour TS de vérifier.

Une autre approche

interface Arglist {
  [index: number]: object;
  0: Function;
}

const a1: Arglist = [func];
const a2: Arglist = [22];                  // fails
const a3: Arglist = [func, "foo"];         // fails
const a4: Arglist = [func, obj];
const a5: Arglist = [func, obj, obj];

5voto

juusaw Points 51

Dans les versions actuelles de Typescript, cela est possible grâce à l'étalement des tableaux :

type FAs = [Function, ...Array<{}>]

Il supporte toute longueur de 1 à n (le premier élément est obligatoire).

0voto

dbandstra Points 1062

Je suis presque sûr que c'est le mieux que l'on puisse faire à partir de Typescript 2.3. Vous pouvez voir des typages comme celui-ci dans lodash par exemple.

interface IMyCaller {
  <R>([fn]: [() => R]): R;
  <R,A>([fn, a]: [(a: A) => R, A]): R;
  <R,A,B>([fn, a, b]: [(a: A, b: B) => R, A, B]): R;
  <R,A,B,C>([fn, a, b, c]: [(a: A, b: B, c: C) => R, A, B, C]): R;
  // keep adding these until you get tired
}

const myCaller: IMyCaller = ([fun, ...args]) => fun.apply(args);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X