37

This one's probably extremely simple but I'm going nuts trying to figure it out.

I have a very simple self-executing function in an outer index.ts file that needs to register a global variable on the window object. I want to assign it like so:

(() => {
  window.myCustomGlobal = new MyCustomGlobal();
})()

I created index.d.ts alongside index.ts:

import { MyCustomGlobal} from './classes';

declare interface Window {
  myCustomGlobal: MyCustomGlobal;
}

No errors in the above, all looks good. The application compiles fine.

In the IDE, however, I get an error: ts2339: Property 'myCustomGlobal' does not exist on type 'Window'

I can't for the life of me figure out what exactly makes Typescript "figure out" what .d.ts file to include. In certain libs, having a .d.ts file alongside a .js file causes it to get picked up, and it works fine. In fact, I used the exact same interface as above with a global third-party lib and it worked great; it just seems like my IDE won't pick it up.

I've tried adding index.d.ts to tsconfig.json in include as well as files with no luck.

Can somebody explain, as if to a child, what causes TS to pick up declaration files? Some days I feel like I get it, and then in stupid simple examples like this I feel like an idiot.

Thanks

6 Answers 6

62

There might be two issues here:

1.) You need to augment Window interface in global scope.

Either remove all import/export keywords to make the containing file a non-module/script. Or you can use declare global in a module to mark everything wrapped in it as global declaration:

import { MyCustomGlobal} from './classes';

declare global {
  interface Window {
    myCustomGlobal: MyCustomGlobal;
  }
}

2.) Equally named files, that only differ in their .ts/.d.ts extension, don't work. To quote the docs:

Please note that the compiler does not include files that can be possible outputs; e.g. if the input includes index.ts, then index.d.ts and index.js are excluded. In general, having files that differ only in extension next to each other is not recommended.

Make sure to give a different name to index.d.ts (like global.d.ts), so the compiler doesn't only pick index.ts. global.d.ts will included automatically, if placed somewhere in the TS project marked by tsconfig.json and if "files" and "include" config options are left unspecified.

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

11 Comments

That was it -- it was the file name. What a way to waste a couple hours trying to figure this out. I had tried the declare global syntax and it wasn't working, but only because of the file name. Thanks a lot!!
but what I can do if I want to write d.ts file by hand to some .js file?
@perymimon Not sure, what you mean. Can you give an example? The precedence order for types is .ts > .d.ts > .js. So, given equally named index.d.ts and index.js file, types are taken from former as desired.
I try to write .d.ts file for .js file that already exist. and I want vscode or typescript recognize the definition so when I hover over the function I will see the definition as in the d.ts file
@perymimon Module resolution should resolve that case automatically, if the .d.ts file has the same path/name as the .js one. This resolution works even in the project, if you don't have a tsconfig.json (just tried it). Above behavior is different for global types (not imported files) - in this case, tsconfig.json exclude rules also play a role. I suggest to open a new question, as this seems to be non-standard behavior.
|
28

We declared "include": ["src"] in our tsconfig.json and this caused declarations.d.ts in root ("/") to not be detected.

1 Comment

thanks. after I included inside "include" it started to work.
7

If you have an import statement in your .d.ts file, it will not work. Remove the import statement and its types should be globally available as expected.

2 Comments

Thanks. I had this problem. Weirdly the exactly same .d.ts with regular import at the top worked for me in another project, but not in my current one. I was able to get it working by importing the type I needed with a dynamic import where I needed to use an external type in my .d.ts like so import('lucide').Icons. After this change the types were detected.
I found that having an export statement also prevented it from working for me.
5

This is just so weird, but, In order for it to work I needed to include the types folder in the include secion in the tsconfig.json

Comments

1

I encountered the same issue in my NodeJS project. I didn't have any import/export in my global.d.ts but still received the error "cannot find the name ..." I resolved this problem by adding "files: ["global.d.ts"]" in tsconfig.json.

tsconfig.json

{ 
  "compilerOptions": {....},
  "files": ["global.d.ts"],
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "global.d.ts"
  ] }

global.d.ts


interface UserToken {
  _id: string;
  email: string;
}

 namespace Express {
  interface Request {
    user: UserToken;
  }
}

and restart your IDE

1 Comment

thank you! to point out: the files have to be named explicitly. a wildcard src/types/*.d.ts didn't work here.
-1

On my end. I have to add DOM under lib in tsconfig.json so typescript compiler recognized window object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.