web-dev-qa-db-fra.com

Comment étendre l'interface TypeScript «Window»

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?

24
Ward

Vous avez besoin du declare global

declare global {
  interface Window {
    fetch:(url: string, options?: {}) => Promise<any>
  }
}

Cela fonctionne alors:

window.fetch('/blah').then(...); 
25
Julian

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.

16
Ryan Cavanaugh