Post

I'm very impressed with the collaboration we've seen from TypeScript to make Node integration a success. It is a team effort with all participants leaning in. Extension rewriting in TS 5.7 is the first treat. This was directly motivated by the Node use-case. And there's more to come! 💙

Rob Palmer@robpalmer.bsky.social

TypeScript 5.7 is released 🎉 🔶 ES2024 library types 🔷 Checker: Never-initialized variables 🔷 Checker: Stricter JSON imports 🔷 Emit: Extension rewriting (*.ts to *.js) 🔷 DTS: Computed methods 🔷 IDE: Better tsconfig discovery 🔷 Perf: Code Caching ⚡️ 2.5x faster startup

Honestly the only change to TS that has made me cringe and think through the use-cases. I'm *very* torn to put it safely.

This is a move that makes it feel like TS is it's own language when it reality it's a superset of JS designed as a superset to work with types stripped off the syntax. Imports are no longer required to be valid for the environment you are authoring.

If this is the direction it's taking, either knowingly or accidentally, another TS / Flow will emerge. I don't want it to, but watch it happen.

0 reposts0 likes

Unfortunately TS is already not a superset of JS. Its syntax is ambiguous enough that some valid JS programs have different semantics when handled by a TS parser. Also not all TS programs can simply have their types stripped off.

There is a rare edge case. Generic invocations, where you can specify the type arguments explicitly when calling a generic function, are in TypeScript since 1.x foo<string>(value) ...in TS means this in JS... (foo < string) > (value) github.com/tc39/proposa...

github.comGitHub - tc39/proposal-type-annotations: ECMAScript proposal for type syntax that is erased - Stage 1ECMAScript proposal for type syntax that is erased - Stage 1 - tc39/proposal-type-annotations

For the last sentence, "not all TS programs can have their types stripped off", there are the usual suspects: namespaces and enums (and experimental decorators, but those are opt-in).

I get it. The rewriting is a semi-complex runtime transform with a runtime helper. One motive is to promote npm packages publishing *.d.ts files. Another is to facilitate maintaining *.js as the executable format for publishing. @searyanc.dev did not merge it accidentally.

I'll have to search through the issues and read through the thought process that lead to the change in opinion from the team.

In short, Node.js started being able to execute TypeScript directly, and we did not want to leave users in a postion where they couldn't publish their TypeScript code without converting all of their code back to JS extension imports that may or may not be exectuable as TS.

To be clear, the positon has always been "TypeScript describes code that can be executed". Node couldn't run TS or with TS extensions, so, we didn't rewrite anything. Now it can, so it should work. May as well make it work well.

Lack of extension rewriting meant I had to take Rollup to emit .js files with correct imports, because tsc would output .js files that imported non-existing .ts files. As a user of tsc, it was a stupid limitation. (I understand it was not actually stupid originally. Still stupid in that use case.)

Use case was a library authored with valid ESM import specifiers, i.e. `import foo from './foo.ts'` instead of `from './foo'`. (There is no 'foo' or 'foo.js' file in that folder.) Solving this without changing the imports to invalid ESM (not my lib, not my choice) was a STRUGGLE.