Reputation: 2253
I'm working on a node.js project that for historical reasons involves both TypeScript and JavaScript. I'd like to set up some project-wide constants that can be used in both languages. Obvious: write a .js
file with the constants, and a .d.ts
file that includes the types for TypeScript's use. But no: several hours of beating on the problem (and RTFMing) have gotten me nowhere.
Here's my first try at the constants file:
// constants.js
const MY_CONST_1 = 1;
exports.MY_CONST_1 = MY_CONST_1;
... and the JavaScript which uses it:
// consumer.js
let constants = require('./constants');
let one = constants.MY_CONST_1;
That works well, but when I try the obvious in TypeScript:
// consumer.ts
import * as constants from './constants';
let one: number = constants.MY_CONST_1;
Nope: error TS2307: Cannot find module './constants'.
So, gotta write a constants.d.ts
file, in the same directory as the constants.js
file, right? Sounds easy, but a half dozen different attempts have yielded exactly zilch. No matter what I do, Typescript complains error TS2306: File '/Users/griscom/Documents/Work/test/constants.d.ts' is not a module
.
So, what would a successful constants.d.ts
file look like? Or, if I'd have to make changes in constants.js
for it all to work, what would they be?
P.S. Here's my tsconfig.json
file:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true,
"noImplicitReturns": true
}
}
(This seems like such a simple and obvious need; it's frustrating how opaque the process is.)
Upvotes: 4
Views: 12530
Reputation: 3061
Another option: using an import for side effects only. Indeed, your constants are global, i.e. not defined in a module due to the missing export
keyword:
import './constants';
To be used in combination with the allowJs
compiler option mentionned in an another response.
Upvotes: 0
Reputation: 52153
allowJs
Try using the compiler option allowJs: true
. This will allow your original import from ./constants
to work even though it's a .js
file, without the need to create a separate .d.ts
file. TypeScript will understand inferrable types from the .js
file, for example you will get type checking against MY_CONST_1
as a number.
As you said in your comment this requires separating your source files from your output files, because it can't output a JS file at the same location as a JS source file.
constants.d.ts
declaration fileGiven your source file that looks like this:
// constants.js
export const MY_CONST_1 = 1;
You can write a constants.d.ts
file that looks like this:
// constants.d.ts
export const MY_CONST_1: number;
Where you were off in your previous attempts is using the declaration module
, which is used to declare types for external modules (like from node_modules
). In this case simply putting the constants.d.ts
file in the same directory as constants.js
and using export
will tell TS that it's a JS module that exports that value:
import { MY_CONST_1 } from "./constants";
import * as constants from "./constants";
Something important to keep in mind is that the .d.ts
file is not checked against the .js
file to ensure it's actually correct, that's on you. So if you make a change to the .js
file you have to make sure to update the .d.ts
file accordingly and correctly. A compile error or lack of compile error does not mean it's correct or not. This is one reason allowJs
exists because it avoids such leaks.
Upvotes: 9
Reputation: 1126
export const MyConst =1;
Or
export class MyGroup {
static MyConst: number
}
Generally stay clear of modules since that isnt compatible with the meaning of modules in inports. Instead use "namespace" which is very similar to a class with static members. Meaning you could probably do (on phone and cant try it out):
export namespace MyNamespace {
export const MyConst = 1;
}
But lastly try avoid wrapping things in extra namespaces and classes etc since the import syntax is the module. Also it makes your code treeshakeable.
Upvotes: 0