Dans mon exemple, j'essaie d'étendre l'interface TS Window pour inclure un polyfill pour fetch
. Pourquoi ça n'a pas d'importance. La question est " comment puis-je dire à TS que window.fetch
est une fonction valide? "
Je fais cela dans VS Code, v.0.3.0 qui exécute TS v.1.5 (IIRC).
Déclarer l'interface dans mon fichier de classe TS où je veux l'utiliser ne fonctionne pas:
///<reference path="typings/tsd.d.ts"/>
interface Window {
fetch:(url: string, options?: {}) => Promise<any>
}
...
window.fetch('/blah').then(...); // TS objects that window doesn't have fetch
Mais c'est OK si je déclare cette même interface dans un fichier ".d.ts" séparé et que je la référence dans mon fichier de classe TS.
Voici "typings/window.extend.d.ts"
///<reference path="es6-promise/es6-promise"/>
interface Window {
fetch:(url: string, options?: {}) => Promise<any>
}
Maintenant, je peux l'utiliser dans mon fichier de classe TS:
///<reference path="typings/window.extend.d.ts"/>
...
window.fetch('/blah').then(...); // OK
Alternativement, je peux écrire une interface d'extension avec un autre nom dans mon fichier de classe TS et ensuite l'utiliser dans un casting:
interface WindowX extends Window {
fetch:(url: string, options?: {}) => Promise<any>
}
...
(<WindowX> window).fetch('/blah').then(...); // OK
Pourquoi l'extension de l'interface fonctionne-t-elle dans un "d.ts" mais pas in situ ?
Dois-je vraiment passer par ces girations?
Vous avez besoin du declare global
declare global {
interface Window {
fetch:(url: string, options?: {}) => Promise<any>
}
}
Cela fonctionne alors:
window.fetch('/blah').then(...);
Lorsque vous avez un import
ou export
de niveau supérieur dans votre fichier (que vous devez trouver quelque part pour avoir ce problème), votre fichier est un module externe.
Dans un module externe, déclarer une interface crée toujours un nouveau type plutôt que d'augmenter une interface globale existante. Cela imite le comportement général des chargeurs de modules - que les choses déclarées dans ce fichier ne fusionnent pas ou n'interfèrent pas avec les choses dans la portée globale.
La raison de cette giration est qu'autrement, il n'y aurait pas moyen, dans un module externe, de définir de nouvelles variables ou types avec le même nom que ceux de la portée globale.