#Force Error on __dirname and __filename

30 messages · Page 1 of 1 (latest)

warm wraith
#

Hey all, I just swapped a few packages over to ESM and I get the, expected, error __dirname is not defined in ES module scope. I swapped over to defining __dirname myself using dirname and fileURLToPath as noted all over. However now I want TS to enforce this.

I have @types/node installed as a dependency and noticed

    var __filename: string;
    var __dirname: string;

Are both declared in globals.d.ts.

Is there a way to tell TS to remove these from the global scope? Or maybe there is another @types package for node-esm? I would just like to enforce that __dirname needs to be defined in code now.

thanks!

hallow latch
#

@warm wraith __dirname and __filename only work in ESM mode

#

when using ES modules, you have to use import.meta.url

#

or use path.dirname from the path builtin module

hallow latch
#

there are plenty of documentation online on how to replace dirname with import.meta.url

#

also, as of node 21, there now is import.meta.dirname and import.meta.filename

warm wraith
#

hey @hallow latch thanks for the reply, but as I mentioned i did swap global __dirname with dirname and fileToPath. It is using import.meta.url as well.

What I was trying to sort out is how to tell typescript to stop thinking global __dirname is acceptable. Like i noted in my first message it seems to be delcared in global.d.ts of @types/node. Is there a way to add my own declaration file indicating these globals should be never or maybe there is another @types package for node-esm?

My code is all working now at runtype. I just want to add type safety to the project and make sure others on the team dont accidently use the global __dfirname

livid pecan
#

You can try declare var __dirname:never;
This doesn't delete the variable, but it does prevent method calls on it or passing it to any functions

#

...what if

Object.defineProperty(globalThis, "__dirname", {
  get(){
    throw new Error("Do not use __dirname");
  }
});

Very bad, but it should prevent using it at runtime... no use as it would probably crash at runtime anyway, please do not use this

hallow latch
#

you cannot remove or overwrite existing types (since other libraries might be depending on those)
but you can add to them (declaration merging)

#

not sure declare var __dirname: never; would work, since it would try to re-declare a symbol that has already been defined, with a different type

#

but tbh, this shouldn't really be a concern

livid pecan
#

It fails if one of the declarations is let/const, or if both declarations are in the same file

#

Probably the reason it works is to allow exactly this

warm wraith
#

I am ok with it not preventing the method calls, the variable wont exist now that i am ending up in ESM mode.

@hallow latch I undertsand TS doesnt know, but I am hoping I could tell it. I don't want any code in our repo, or evben other libraries in my projec, to use __dirname either. When this is bundled up it will be running in ESM mode so it will not exist for sure.

@livid pecan where did you set this? did you just make a globals.d.ts?

hallow latch
warm wraith
#

Eh i dunno, seems like this should be a compiler failure. The variable doesnt exist. I think the issue is really in the @types/node package

hallow latch
#

nah, not really

#

you want to forbit certain constructs based on personal preferences

#

that's a point of a linter

#

not a compiler

warm wraith
#

I dont think its personal preference though. Switching into ESM mode causes nodeJS to not have those globals.

haha if i had personal preference I would have just left the dang global.

#

It seems like package.json exports does not allow different types for cjs vs esm :/

Something like this

  "exports": {
    ".": {
      "require": "./dist/index.js",
      "import": "./dist/index.mjs",
      "types": "./dist/index.d.ts"
    }
  },

but I would need different types for require vs import. this would allow @types/node to just ship different global.d.ts

I was not able to get the declare var __dirname: never so I am likely doing something wrong there as well.

Honestly I am thinking my best bet is just to let pnpm patch @types/node and remove these lines

    var __filename: string;
    var __dirname: string;

    var require: NodeRequire;
    var module: NodeModule;

    // Same as module.exports
    var exports: any;
livid pecan