304

I have added TS to my React/Redux app.

I use window object in my app like this:

componentDidMount() {
  let FB = window.FB;
}

TS throws an error:

TypeScript error: Property 'FB' does not exist on type 'Window'. TS2339

I want to fix the error.

1 (doesn't work)

// Why doesn't this work? I have defined a type locally

type Window = {
  FB: any
}

componentDidMount() {
  let FB = window.FB;
}

// TypeScript error: Property 'FB' does not exist on type 'Window'. TS2339

2 (fixes the error)

I found the answer here https://stackoverflow.com/a/56402425/1114926

declare const window: any;

componentDidMount() {
  let FB = window.FB;
}
// No errors, works well

Why doesn't the first version work, but the second does, even though I do not specify FB property at all?

2
  • 1
    Do you use modules ? The answer differs a bit depeding on that Commented Jun 5, 2019 at 9:40
  • I use React components. All the behavior above is from React components. They may be called sort of modules because they incapsulate logic Commented Jun 5, 2019 at 9:43

15 Answers 15

523

Why does declare const window: any; work?

Because you declare a local variable of type any. Having something of type any essentially turns off type checking for window so you can do anything with it. I really do not recommend this solution, it is a really bad one.

Why doesn't type Window = { FB: any } work? You define a type Window. This type if defined in a module has nothing to do with the type of the global window object, it is just a type that happens to be called Window inside your module.

The good solution To extend window you must extend the global Window interface. You can do this like this:

declare global {
    interface Window {
        FB:any;
    }
}

let FB = window.FB; // ok now

Note that this extension is going to be available in your whole project not just the file you define it in. Also if FB has definitions you might consider typing it a bit better (FB: typeof import('FBOrWhateverModuleNameThisHas'))

Sign up to request clarification or add additional context in comments.

13 Comments

Your "good solution" doesn't compile."Property FB does not exist on type window & typeof globalThis"
@jtiscione yes it does typescriptlang.org/play?noImplicitReturns=false#code/… if your file is not a module, remove the declare global typescriptlang.org/play?noImplicitReturns=false#code/…
Why is this answer not marked as the Answer? I looked long and far to find a method to access reactive state functions from the console/external JS and this is the only one that compiled in TS and worked
@Beerswiller Because the OP couldn't get it to work and didn't bother to follow up 🤷‍♂️
If anyone is struggling with this answer on angular, put this code declare global { interface Window { FB:any; } } inside main.ts
|
108

There are a few ways to solve this problem.

Some examples:

1-) Do a cast

(window as any).X

2-) Put the following code in a file named react-app-env.d.ts

interface Window {
  X?: {
    Y?: {
      .......
    }
  }
}

2 Comments

W̶i̶n̶d̶o̶w̶s̶ (window as any).X
In case of Vite - vite-env.d.ts file
33

you can solve the problem easily without any need to declaration

window["FB"]

UPDATE
since it's a workaround without any compiler configuration to ensure your program's compatibility with typescript maybe you will need just a type validation.

if(window["FB"]) {
  // do some FB logic
}

5 Comments

That didn't work, it says TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
@shamaseen this is the fastest way to solve the problem if you have specific type for index, you can use Titian's solution
If you get the TS7015: Element implicitly has an 'any' type because index expression is not of type 'number' message, the following tsconfig.json property/value can be used to suppress it: "suppressImplicitAnyIndexErrors": true
Don't suppress errors. The point of TypeScript is to catch errors like this.
@A-Diddy You know the easiest way to suppress errors in Typescript is to use Javascript, right? If you're going to silence errors, why use Typescript? It's not like a truly static language where making the compile errors disappear is the same thing as fixing them. All you're doing is saying "I know better than you TS, shut up". But the whole reason for using Typescript is because most of us have learned, we usually don't know better than the compiler, at least not as the project grows or time passes on, and once you've silenced all the warnings, it's just JS or maybe even worse.
30

Solution for the problem "Property does not exist on type Window in TypeScript":

STEP:1 In your src directory, create a types directory that contains the following index.d.ts file: src/types/index.d.ts

export {};

declare global {
  interface Window {
    example: string; // whatever type you want to give. (any,number,float etc)
  }
}

STEP: 2 add the path to your types directory to your tsconfig.json file.

tsconfig.json

{
  "compilerOptions": {
    // ... rest
    "typeRoots": ["./node_modules/@types", "./src/types"]
  }
}

STEP: 3 Now use it, whereever you want to do it.

window.example = 'hello';

console.log(window.example);

2 Comments

Why do you consider this a "HACK SOLUTION"?
@Fatedx it works really well! i was messing around with so many things but this worked really well so i just said HACK SOLUTION because it resolved the problem. :)
18

I use this without declare global

declare const window: Window &
   typeof globalThis & {
     FB: any
   }

3 Comments

There is a bracket too much... removing it I get Cannot redeclare block-scoped variable 'window'
I did this too.
This works for VITE
11

I was facing this issue in my angular code. Below solution helped me to resolve the issue.

I resolved this error by creating a folder name types inside src and inside that folder created index.d.ts file.

the index.d.ts file will have below code.

export {};
declare global {
  interface Window {
    chrome: any;  // this will be your variable name
  }
}

If the error persists, try adding the path to your types directory to your tsconfig.json file.

{
  "compilerOptions": {
    // ... rest
    "typeRoots": ["./node_modules/@types", "./src/types"]
  }
}

Comments

10

it should be ignored by creating global.d.ts file in root of project with this content:

export { }
declare global {
    interface Window {
        [key: string]: any 
    }
}

it ignores all variables of window object

1 Comment

It doesn't "ignore" all window variables, it just doesn't enforce strict rules. Better though is to use "string" instead of "any".
5

better still

declare global {
  interface Window {
    FB: {
      CustomerChat: {
        hide: () => void;
        show: () => void;
      };
    };
  }
}

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
3

This worked for me without declaring it globally

declare const window: Window &
   typeof globalThis & {
     FB: any
   }

This was the error I was facing Error: Property 'name' does not exist on type '{}'.ts(2339) Although mine wasn't really related with your code but this guide should help you

Comments

3

Use a temp variable and cast it to any

const tempWindow: any = window;
const anyProperty = tempWindow.anyProperty;

Comments

1

Create global.d.ts:

interface Window {
    FB: unknown // if you know the shape, use that
}

global.d.ts assumes the whole declare global{} part so shouldn't need to wrap your types in it.

For all your app specific, non-global types/interfaces, use index.d.ts. If you have library specific types, I like to put them in a folder like types/react/index.d.ts

Comments

0

For anyone coming from Next.Js, you need to use <Script /> inside of <body> to load it (loading it inside of the <Head /> won't work):

https://nextjs.org/docs/basic-features/script

Comments

0

I've just added a Window interface in a file called global.d.ts inside the src directory in my react app like this:

interface Window {
  TOKEN: string;
}

The error is gone and I can assign the TOKEN variable like this without any issue:

window.TOKEN = process.env.TOKEN as string;

Comments

0

Another way of bypassing index.d.ts file is to cast it with types.

Extending @Fábio answer, instead of:

(window as any).X

You could:

(window as Window & typeof globalThis & { x: string }).x

Works great if you are looking for a one-time solution without using any

Comments

0

There's got to be a better way to get a properly types Window object in 2025...

export interface CSSMatrix {
  a: number;
  b: number;
  c: number;
  d: number;
  e: number;
  f: number;
  m11: number;
  m12: number;
  m13: number;
  m14: number;
  m21: number;
  m22: number;
  m23: number;
  m24: number;
  m31: number;
  m32: number;
  m33: number;
  m34: number;
  m41: number;
  m42: number;
  m43: number;
  m44: number;
}

declare global {
  interface Window {
    WebKitCSSMatrix?: CSSMatrix;
    MSCSSMatrix?: CSSMatrix;
    CSSMatrix?: CSSMatrix;
  }

  interface CSSStyleDeclaration {
    animatingX?: string;
    animatingY?: string;
  }
}

// This empty export makes this file a module
export {}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.