TS1479, helmet typings issue in combination with fastify
Uzlopak opened this issue · comments
In combination with fastify, I get this error.
fastify/fastify-helmet#210
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Fastify version
4.10.2
Plugin version
10.1.0
Node.js version
16.17.0
Operating system
Linux
Operating system version (i.e. 20.04, 11.3, 10)
22.04
Description
It seems that we get typescript errors, because the typings from helmet are ecmascript and not commonjs
uzlopak@Battlestation:~/workspace/nodenext-mvce$ npm run build
> nodenext-test@1.0.0 build
> tsc -p .
node_modules/@fastify/helmet/types/index.d.ts:2:62 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("helmet")' call instead.
2 import helmet, { contentSecurityPolicy, HelmetOptions } from 'helmet';
~~~~~~~~
Found 1 error in node_modules/@fastify/helmet/types/index.d.ts:2
Steps to Reproduce
clone https://github.com/Uzlopak/nodenext-mvce/tree/helmet-issue
npm run build
Expected Behavior
Should not throw
This looks like an issue with fastify-helmet
and not Helmet itself, so I'm going to close. Let me know if that's wrong and I'll reopen!
@EvanHahn
The problem is helmet
only provide ESM
types but not CJS
types.
When using with "type": "module"
in package.json
and "module": "NodeNext", "moduleResolution": "Node16"
in TypeScript
. The mismatch of types will throw an error, sine TypeScript
think that it is a ESM
module only.
Do you experience this problem with Helmet directly
Yes.
// tsconfig.json
{
"compilerOptions": {
"moduleResolution": "NodeNext"
}
}
// index.ts
import helmet from 'helmet'
helmet
// package.json
{
"dependencies": {
"helmet": "^6.0.0"
},
"devDependencies": {
"@types/node": "^18.11.9",
"typescript": "^4.9.3"
}
}
Thanks. I'm able to reproduce the problem, but I think this working as expected. I don't think you should be able to import helmet from 'helmet'
in CommonJS mode. If you add "type": "module"
to your package.json
, it should work.
Does that help?
Does that help?
No, it is the problem of mis-match of types.
You can use import helmet from 'helmet'
, but TypeScript
provide more combination then you though.
Forcing people to use certain configuration is not optimal for a library. And the solution is as simple as provide the correct types for both CJS
and ESM
.
TypeScript
itself it blaming library from serving the incorrect types harder and harder when it evolving.
If you add "type": "module"
, the problem solve only to suppress the TypeScript
error.
But, when you check the output of file. Yes, it is using CJS
as intended and the package.json
is telling Node.JS
to run as ESM
.
Thus, the problem is not solved at all. But bring to a runtime error.
Are there libraries that do a better job here? I have had trouble making things work seamlessly with CommonJS + ESM + TypeScript.
Are there libraries that do a better job here?
Not the best example, but it is how I do in TypeScript
. https://github.com/climba03003/fastify-bree
When you provide the *.d.ts
file next to *.js
, TypeScript
actually prefer that types file first. (Maybe, it is the extra package.json
trigger this behavior.)
So, the easiest way should be emit proper types
under the dist/cjs
.
Maybe this should be reopened, since issue still exists, and requires a solution?
Maybe this should be reopened, since issue still exists, and requires a solution?
Done!
I won't have time to investigate this in 2022. If anyone would like to submit a pull request, I'm happy to take a look!
Still a problem, for anyone who comes across this issue. TS5 + Nodejs 19
I believe I have fixed this in #405. Please try that to see if it fixes your issue.
@EvanHahn sorry, but I'm still getting the error:
module "/home/.../Documents/.../gt-be/node_modules/helmet/dist/esm/esm" The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("helmet")' call instead. To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field
"type": "module"to '/home/.../Documents/.../gt-be/package.json'.ts(1479)
I'm using
`
"packageManager": "npm@9.6.2",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"helmet": "https://evanhahn.com/tape/helmet-6.0.1.tgz",
"mongodb": "^5.1.0"
},
"engines": {
"node": ">=19.8.1"
},
"devDependencies": {
"@types/cors": "^2.8.13",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.0",
"@types/node": "^18.15.3",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"eslint": "^8.36.0",
"jest": "^29.5.0",
"nodemon": "^2.0.20",
"rimraf": "^4.4.0",
"supertest": "^6.3.3",
"ts-jest": "^29.0.5",
"ts-node": "^10.9.1",
"typescript": "^5.0.2"
}
}
Thanks for testing this. What does your tsconfig.json
look like?
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file /
"target": "ES2022", / Set the JavaScript language version for emitted JavaScript and include compatible library declarations. /
"module": "CommonJS", / Specify what module code is generated. /
"rootDir": ".", / Specify the root folder within your source files. /
"moduleResolution": "node16", / Specify how TypeScript looks up a file from a given module specifier. /
"resolveJsonModule": true, / Enable importing .json files. /
"declaration": true, / Generate .d.ts files from TypeScript and JavaScript files in your project. /
"sourceMap": true, / Create source map files for emitted JavaScript files. /
"outDir": "build", / Specify an output folder for all emitted files. /
"esModuleInterop": true, / Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. /
"forceConsistentCasingInFileNames": true, / Ensure that casing is correct in imports. /
"strict": true, / Enable all strict type-checking options. /
"noImplicitAny": true, / Enable error reporting for expressions and declarations with an implied 'any' type. /
"strictNullChecks": true, / When type checking, take into account 'null' and 'undefined'. /
"noImplicitThis": true, / Enable error reporting when 'this' is given the type 'any'. /
"noUnusedLocals": true, / Enable error reporting when local variables aren't read. /
"noUnusedParameters": true, / Raise an error when a function parameter isn't read. /
"noImplicitReturns": true, / Enable error reporting for codepaths that do not explicitly return in a function. /
"noFallthroughCasesInSwitch": true, / Enable error reporting for fallthrough cases in switch statements. /
"skipLibCheck": true / Skip type checking all .d.ts files. /
},
"include": ["src"],
"exclude": ["src/**/.test.ts", "build/**", "node_modules"]
}
Thanks. I am working on a fix for this.
This should be fixed in helmet@6.1.0
.