27
loading...
This website collects cookies to deliver better user experience
require("module")
most typescript applications use some variation of import module from "module"
. import module from "module"
directly in your transpiled code..mjs
suffix on your files or you can set the type: "module"
property in your package.json. The mjs suffix isn’t really relevant or practical when using typescript so it’s easier just to set the type property in your package.json file.type
to module."name": "shared-api-client",
"version": "1.0.0",
"description": "OpenAPI client for shared-api-client",
"author": "OpenAPI-Generator",
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
"type": "module",
type: "module"
if you’re publishing a package with ECMAScript es6 Modules.node package/main.js
it will fail with an error ERR_MODULE_NOT_FOUND.node --es-module-specifier-resolution=node main.js
// Do this if you don't want to specify --es-module-specifier-resolution=node (note the .js)
import mod from "./myModule/mod.js"
// Don't do this without specifying resolution like above!
import mod from "./myModule/mod"
import fs from 'fs/promises'
// this is ok because it's in an async function
const myFunc = async () => {
await fs.readFile('path')
}
// this fails to compile in tsc because it is at the top level of a module
await fs.readFile('path')
// just to make this a module
export {}
import dotenv from 'dotenv'
import { AuthenticatedRequests } from './commonDataModels/AuthenticatedRequests'
dotenv.config()
// async function that gets a valid auth token from a third party service so we can build requests
await AuthenticatedRequests.setToken()
export {}
.then()
promise syntax in the setToken()
method and make it a synchronous method. But I much prefer using async await where I can..mjs
file the top level await should just work for you.require()
any commonjs modules in your own modules anymore. You have to import them using import syntax.esModuleInterop
in their tsconfig file. Then you can just use a “normal” import.// this imports the default export from a commonjs module.
import dotenv from 'dotenv'
// this imports default and any named exports on module.exports
import * as dotenv from 'dotenv'
// you could access dotenv.default here
// or const postConfig = dotenv() (dotenv module doesn't export a function on exports but this is just an example)
import.meta.
. Here’s how to use it.console.log(import.meta.url)
// returns where the module (usually the file) is located e.g. file:///Users/me/personal-projects/blog/e2e-backend/src/preRun.ts
// and how to get a string file path
console.log(new URL('./new-file-path.json', import.meta.url).pathname)
// returns e.g. /Users/me/personal-projects/blog/e2e-backend/src/new-file-path.json
fs
method with a URL
instance directly but the typings I used in my application required a string to be passed. So that’s why I pass the .pathname
property of the URL to fs methods.// this works on my application with installed Node.js types
const contents = fs.readFileSync(
new URL('./new-file-path.json', import.meta.url).pathname
)
// this is how the Node.js docs suggest using URL with fs methods but this did not
// pass with my typescript Node.js types
const contents = fs.readFileSync(
new URL('./new-file-path.json', import.meta.url)
)
es2020
module. Like this{
"compilerOptions": {
"lib": ["es2020"],
"module": "es2020",
"target": "es2020",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true
}
}
esnext
like this.esnext
is designed to contain experimental features so you might not want to use it in production.{
"compilerOptions": {
"lib": ["es2020"],
"module": "esnext",
"target": "es2020",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true
}
}
{
"compilerOptions": {
"lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string"],
"module": "esnext",
"target": "es2019",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true
}
}
import.meta
property you need to replace __filename
with is only available in es2020 module or higher (“esnext” would also have it).npm i --save-dev ts-jest
// or
// yarn add -D ts-jest
{
"preset": "ts-jest",
"roots": ["<rootDir>/src"],
"extensionsToTreatAsEsm": [".ts"],
"testRegex": ".e2e-spec.ts$",
"setupFiles": ["<rootDir>/src/preRun.ts"],
"globals": {
"ts-jest": {
"useESM": true
}
}
}
//in package.json scripts
"test": "NODE_OPTIONS=--experimental-vm-modules npx jest"
node:
schema so you can make it clear that this import is a node module and not a custom application module.import fs from 'node:fs'