Conflicting Typescript declaration exports with @types/node


#1

Hi all,

I should clarify, I wasn’t too sure on the most appropriate sub-forum for this post, here goes anyhow.

There is a conflict between FiveM’s typescript declaration file and @types/node, specifically with the exports declaration

@types/node declares the global variable exports as well and a conflict arises when using both declarations.

$ tsc
node_modules/@types/node/index.d.ts:289:13 - error TS2451: Cannot redeclare block-scoped variable 'exports'.

289 declare var exports: any;
                ~~~~~~~

  ../typings/fivem.d.ts:80:15
    80 declare const exports: any;
                     ~~~~~~~
    'exports' was also declared here.

../typings/fivem.d.ts:80:15 - error TS2451: Cannot redeclare block-scoped variable 'exports'.

80 declare const exports: any;
                 ~~~~~~~

  node_modules/@types/node/index.d.ts:289:13
    289 declare var exports: any;
                    ~~~~~~~
    'exports' was also declared here.


Found 2 errors.

Of course, the obvious fix is to remove the second exports declaration from FiveM’s declaration file in my development environment, however, I know that FiveM installs some magic in the exports global but I don’t necessarily believe that this is best practice in the first place.

As an intermediary fix, can I suggest that CitizenFX change the declaration for exports in their type declaration file to be:

declare var exports: any;

so that it is compatible with @types/node’s declaration?

I would actually like to initialise a discussion around whether overriding the exports global is best practice and how CitizenFX currently has the opportunity to change this practice before the JS resource scene explodes. Can I propose that maybe another unused global is used or that there is better integration implemented into FiveM/FiveM’s Node.js fork with FiveM resources and Node.js modules?

Kind regards


#2

Odd - we’ve not hit this earlier, even when using both @types/node as well as @citizenfx/server (or @citizenfx/client). Might it be @types/node (or the TypeScript compiler?) changed at some point to make duplicate definitions error out? :confused:

In the CitizenFX runtime it’s an actual global; in the CommonJS ecosystem this is not typically a global (in fact, it’s a function-scoped variable handled by Node.js’ module library), unless this changed in newer Node.js versions (we’re currently on v8.x, and it’s unlikely it’ll be upgraded soon enough since we had to heavily patch Node.js for event loop integration). It might be the typings still consider it a global, however this is factually incorrect for at least Node 8 (i.e. global.exports wouldn’t exist typically - it does in FiveM as it’s an actual global).


#3

It appears you’re correct about exports, documentation for reference: https://nodejs.org/api/modules.html#modules_exports
I apologise for my misunderstanding…

I wasn’t aware that @citizenfx/server and @citizenfx/client existed - I did search NPM for fivem :roll_eyes:

I retired with the “official” typings with the same result:

$ tsc
node_modules/@citizenfx/server/index.d.ts:82:15 - error TS2451: Cannot redeclare block-scoped variable 'exports'.

82 declare const exports: any;
                 ~~~~~~~

  node_modules/@types/node/index.d.ts:289:13
    289 declare var exports: any;
                    ~~~~~~~
    'exports' was also declared here.

node_modules/@types/node/index.d.ts:289:13 - error TS2451: Cannot redeclare block-scoped variable 'exports'.

289 declare var exports: any;
                ~~~~~~~

  node_modules/@citizenfx/server/index.d.ts:82:15
    82 declare const exports: any;
                     ~~~~~~~
    'exports' was also declared here.


Found 2 errors.


#4

Ah!

This indeed changed in an update to @types/node - however since this is Node.js 8.x, you should use the v8 versions of @types/node.

… except those changed this too. Dammit!

We would break compatibility with old versions if we’d change this, as well. :confused: Perhaps temporarily use a version from before that commit?