Je voudrais définir un type pour un tableau dont le premier élément est un type spécifique (par exemple Function), et les éléments restants sont le type vide. Par exemple:
type FAs = [Function, {}, {}, {}, ...]; // pseudo code
Une telle chose est 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érerais utiliser un seul argument. Je me demande également si le système de type prend en charge ce qui est sans doute un tuple de longueur arbitraire. Peut-être qu'une telle chose n'est pas souhaitable pour des raisons informatiques que je ne comprends pas.
Si vous définissez
type FAs = [Function, {}];
Les valeurs de type FAs
nécessiteront alors un premier élément de type Function
, un deuxième élément de type {}
, et les éléments suivants de Function | {}
. C'est ainsi que fonctionnent les types de tableaux littéraux TypeScript. À partir de TS docs :
Lors de l'accès à un élément en dehors de l'ensemble des indices connus, un type d'union est utilisé à la place:
Cela devrait faire tout ce que vous voulez sauf pour le fait que vous pourrez passer une valeur typée 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 cela. Il n'y a aucun moyen dans TS de définir un type de tableau où les premiers éléments n sont de certains types spécifiques, et il existe un nombre arbitraire d'éléments restants d'un autre type spécifique.
Je me demande également si le système de type prend en charge ce qui est sans doute un tuple de longueur arbitraire.
En fait, le système de type uniquement prend en charge les tuples de longueur arbitraire. Si tu le dis
type Tuple = [number, number];
ce type est compatible avec n'importe quel tableau de longueur deux ou plus , qui contient des nombres. Si tu le dis
type Tuple = [string, number];
ce type est compatible avec n'importe quel tableau, de longueur deux ou plus , qui a une chaîne comme premier élément, un nombre comme deuxième, et soit un chaîne ou nombre comme troisième etc. Je n'appellerais pas les raisons de ce comportement "basées sur l'informatique"; c'est plus une question de ce qu'il est possible pour TS de vérifier.
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];
Dans les versions actuelles de TypeScript, cela est possible en utilisant la propagation de tableau:
type FAs = [Function, ...Array<{}>]
Il prend en charge n'importe quelle longueur de 1 à n (le premier élément est requis).
Je suis presque sûr que c'est le meilleur que vous puissiez faire avec TypeScript 2.3. Vous pouvez voir des saisies comme celle-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);