3 ms·
Did anyone make a large TypeScript codebase work with ESM + TS + node (together with IDE support and yarn pnp support?) The thing that is annoying with ESM is
by jakub_g 2y ago
Did anyone make a large TypeScript codebase work with ESM + TS + node (together with IDE support and yarn pnp support?)
The thing that is annoying with ESM is that it requires to have extensions in imports, i.e. `import .. from '/foo.js'`.
This gets messy with TypeScript, where your files are named `foo.ts` but you need to import `foo.js`.
The previous "best practice" in TS world was to have extensionless JS imports, so this move would require a massive codemod to update all imports in an entire codebase.
For now, we've been using `ts-node` with swc under the hood, but without ESM. I tried `tsx`, but the compilation time of esbuild is way too slow, some of our node CLI tools written in TS take 15s to boot up, which is not acceptable (with `ts-node` it's 3-4s) (tbh, it's probably partly a fault of our CLI framework, which crawls all workspaces to discover all CLI tools, and as we have a lot of them, tsx has a lot of useless work to do).
- gauben 2y agoHey! Not sure how modern your codebase is, but you can consider the following tsconfig settings: - rewriteRelativeImportExtensions: this will allow you to write `import foo from './foo.ts'` and have tsc transform it to `import foo from './foo.js'` - erasableSyntaxOnly: this will error on non "erasable" syntax, that is, TypeScript code that has a runtime output (e.g. enums) With these two settings enabled, you'd be able to run TypeScript code directly with Node: `node src/index.ts`, and cut boot up time substantially
- hombre_fatal 2y agoTo add, those are the recommended tsconfig.json settings in Node's docs on native TS stripping. Here are the rest: https://nodejs.org/api/typescript.html#type-stripping https://nodejs.org/api/typescript.html#type-stripping
- WorldMaker 2y agoAlso there are eslint rules older than erasableSyntaxOnly that can also be useful in doing a "rip-the-bandaid-off-refactor" using all the lint warnings/warnings-as-errors to add extensions everywhere in the case where your brownfield also needs to be a version or two behind on Typescript.
- hakkotsu 2y agoWhile `rewriteRelativeImportExtensions` works for frontend applications, it has a significant limitation: it doesn't fix declaration files (.d.ts), which is problematic when developing libraries or public packages. I created a small tool to address ESM + TypeScript issues that the tsc doesn't handle: https://github.com/2BAD/tsfix https://github.com/2BAD/tsfix
- tsarchitect 2y agoHow about for aliases? import foo from '@Schemas/foo.ts' won't work since it is not a 'RelativeImport'. Is there a fix for this use case?
- paulddraper 2y agoIt’s pretty easy to find/replace everywhere that needs it. In my experience the reason people don’t is that it offends their aesthetics. Which I understand. But personally I don’t program for aesthetics.
- theogravity 2y agoI use a custom loader to deal with this: https://github.com/theogravity/fastify-starter-turbo-monorepo/blob/main/apps/backend/loader.js https://github.com/theogravity/fastify-starter-turbo-monorep... Usage: Search for loader.js refs. https://github.com/theogravity/fastify-starter-turbo-monorepo/blob/main/apps/backend/package.json https://github.com/theogravity/fastify-starter-turbo-monorep...