Pourquoi TypeScript a-t-il un type puis un "type similaire"? Un exemple de ceci est Promise<T>
et PromiseLike<T>
. Quelles sont les différences entre ces deux types? Quand dois-je les utiliser? Dans ce cas, pourquoi ne pas avoir un seul type Promise
?
Si vous regardez les fichiers de définition (prenons lib.es6.d.ts ) alors c'est assez simple.
Par exemple, l'interface ArrayLike :
interface ArrayLike<T> {
readonly length: number;
readonly [n: number]: T;
}
est plus limité que le Array one:
interface Array<T> {
length: number;
toString(): string;
toLocaleString(): string;
Push(...items: T[]): number;
pop(): T | undefined;
concat(...items: T[][]): T[];
concat(...items: (T | T[])[]): T[];
join(separator?: string): string;
reverse(): T[];
shift(): T | undefined;
slice(start?: number, end?: number): T[];
sort(compareFn?: (a: T, b: T) => number): this;
splice(start: number, deleteCount?: number): T[];
splice(start: number, deleteCount: number, ...items: T[]): T[];
unshift(...items: T[]): number;
indexOf(searchElement: T, fromIndex?: number): number;
lastIndexOf(searchElement: T, fromIndex?: number): number;
// lots of other methods such as every, forEach, map, etc
[n: number]: T;
}
C'est bien d'avoir les deux séparés parce que je pourrais vouloir avoir une fonction comme celle-ci:
function getSize(arr: Array<any>): number {
return arr.length;
}
console.log(getSize([1, 2, 3])); // works
Mais cela ne fonctionnera pas avec ceci:
function fn() {
console.log(getSize(arguments)); // error
}
Il en résulte cette erreur:
L'argument de type "IArguments" n'est pas attribuable au paramètre de type "any []".
La propriété 'Push' est manquante dans le type 'IArguments'.
Mais les deux fonctionneront si je fais cela:
function getSize(arr: ArrayLike<any>): number {
return arr.length;
}
(plus sur ArrayLike dans MDN )
La même chose avec Promise
et PromiseLike
, si je construis une bibliothèque qui n'est pas d'opinion sur l'implémentation de Promise
alors au lieu de faire ceci:
function doSomething(promise: Promise<any>) { ... }
Je vais faire ça:
function doSomething(promise: PromiseLike<any>) { ... }
Ensuite, même si l'utilisateur de ma bibliothèque utilise une implémentation différente (bluebird), cela fonctionnera très bien.
Si vous remarquez la définition de Promise est la suivante:
declare var Promise: PromiseConstructor;
Ce qui le rend très spécifique, d'autres implémentations peuvent avoir des propriétés différentes, par exemple un prototype différent:
interface PromiseConstructor {
readonly prototype: Promise<any>;
...
}
Je suppose que la principale raison pour laquelle nous avons PromiseLike
est que plusieurs implémentations étaient disponibles avant que la native ne soit prise en charge (comme bluebird , Promises/A + , jQuery , et plus).
Pour que TypeScript fonctionne avec les bases de code qui utilisent ces implémentations, il doit y avoir un type autre que Promise
, sinon il y aurait beaucoup de contradictions.