Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extend the 'Window' typescript interface

In my example, I'm trying to extend the TS Window interface to include a polyfill for fetch. Why doesn't matter. The question is "how do I tell TS that window.fetch is a valid function?"

I'm doing this in VS Code, v.0.3.0 which is running TS v.1.5 (IIRC).

Declaring the interface inside my TS class file where I want to use it doesn't work:

///<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 

But it's OK if I declare this same interface in a separate ".d.ts" file and reference it in my TS class file.

Here is "typings/window.extend.d.ts"

///<reference path="es6-promise/es6-promise"/> interface Window {   fetch:(url: string, options?: {}) => Promise<any> } 

Now I can use it in my TS class file:

///<reference path="typings/window.extend.d.ts"/> ... window.fetch('/blah').then(...); // OK 

Alternatively, I can write an extending interface with another name in my TS class file and then use it in a cast:

interface WindowX extends Window {   fetch:(url: string, options?: {}) => Promise<any> } ... (<WindowX> window).fetch('/blah').then(...); // OK 

Why does extending the interface work in a "d.ts" but not in situ?

Do I really have to go through these gyrations?

like image 470
Ward Avatar asked Jun 21 '15 01:06

Ward


People also ask

Can I extend interface in TypeScript?

In TypeScript, interfaces can extend each other just like classes.

Does not exist on window TypeScript?

The "Property does not exist on type 'Window & typeof globalThis'" error occurs when we access a property that does not exist on the Window interface. To solve the error, extend the Window interface in a . d. ts file and add the property you intend to access on the window object.


2 Answers

You need the declare global

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

This works then:

window.fetch('/blah').then(...);  
like image 120
Julian Avatar answered Sep 29 '22 10:09

Julian


When you have a top-level import or export in your file (which you must somewhere to be having this problem), your file is an external module.

In an external module, declaring an interface always creates a new type rather than augmenting an existing global interface. This mimics the general behavior of module loaders -- that things declared in this file don't merge or interfere with things in the global scope.

The reason for this gyration is that otherwise there wouldn't be a way to, in an external module, define new variables or types with the same name as those in the global scope.

like image 25
Ryan Cavanaugh Avatar answered Sep 29 '22 10:09

Ryan Cavanaugh