|
| 1 | +# Strip Types Design |
| 2 | + |
| 3 | +## Problem |
| 4 | + |
| 5 | +TypeScript support has been for a few years at the top of the list of features that users want to see in Node.js. |
| 6 | +Discussion has been on going for a few years [#43818](https://github.com/nodejs/node/issues/43818), and the main blocker has been the lack of a clear on long term support. |
| 7 | +TypeScript does not follow semver, and the Node.js project has been reluctant to commit to supporting TypeScript in the long term, given that the lifespan of an LTS version is 3 years. |
| 8 | + |
| 9 | +## Proposal |
| 10 | + |
| 11 | +The proposal is to add a new flag to the Node.js CLI, `--experimental-strip-types`, which will replace inline TypeScript types with whitespace. |
| 12 | +No type checking is performed, and types are discarded. |
| 13 | + |
| 14 | +Example: |
| 15 | + |
| 16 | +```typescript |
| 17 | +interface Foo { |
| 18 | + bar: string; |
| 19 | +} |
| 20 | + |
| 21 | +throw new Error("Whitespacing"); |
| 22 | + |
| 23 | +``` |
| 24 | + |
| 25 | +Becomes: |
| 26 | + |
| 27 | +```javascript |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | + |
| 32 | +throw new Error("Whitespacing"); |
| 33 | + |
| 34 | +``` |
| 35 | + |
| 36 | +>Note that the missing types are replaced with whitespace, so the line numbers are preserved, so that sourcemaps are not needed. |
| 37 | +
|
| 38 | +By removing types completely, we can avoid the need to commit to supporting TypeScript in the long term, as the feature is not a full TypeScript implementation. We won't need to worry about breaking changes in TypeScript, as we are not implementing them. |
| 39 | +TypeScript features that cannot be replaced by whitespace, such as enums, will error. |
| 40 | +As in JavaScript files, file extensions are required in `import` statements and `import()` expressions. |
| 41 | +TypeScript features that depend on settings within `tsconfig.json`, such as paths or converting module formats, are unsupported. |
| 42 | +This will solve the long term compatibility issue, but might not be as complete as a full TypeScript implementation. |
| 43 | + |
| 44 | +### Goals |
| 45 | + |
| 46 | +#### Determining module system |
| 47 | + |
| 48 | +TypeScript supports multiple module systems, such as CommonJS, ES Modules. |
| 49 | +We want to avoid the need to parse `tsconfig.json` to determine the module system, as this would require a full TypeScript implementation. |
| 50 | +We want to be able to support `.mts` and `.cts` files, and both module systems in `.ts`. |
| 51 | + |
| 52 | +#### TypeScript only features |
| 53 | + |
| 54 | +TypeScript has features that cannot be replaced by whitespace. |
| 55 | +The most prominent unsupported features that require transformation are: |
| 56 | + |
| 57 | +* `Enum` |
| 58 | +* `experimentalDecorators` |
| 59 | +* `namespaces` |
| 60 | +* `module` declaration |
| 61 | + |
| 62 | +With types stripped, unless transformation is performed, these features will error. |
| 63 | +This is probably the biggest limitation of this proposal, since we are not implementing these features. |
| 64 | + |
| 65 | +#### Source maps |
| 66 | + |
| 67 | +Sourcemaps are currently not supported, but we should consider adding support in the future. |
| 68 | + |
| 69 | +#### Extension guessing |
| 70 | + |
| 71 | +Importing modules without extension is a **no goal**, file extensions are **always** required: |
| 72 | + |
| 73 | +```ts |
| 74 | +import { foo } from './foo'; // it will not work |
| 75 | +import { foo } from './foo.ts'; // it will work |
| 76 | +``` |
| 77 | + |
| 78 | +[TypeScript documentation](https://www.typescriptlang.org/docs/handbook/modules/reference.html) suggest that the file extension should be `.js` when importing TypeScript files. |
| 79 | +This is mostly for compatibility with other tools, such as bundlers, so that once the TypeScript is compiled, the extension is `.js`. |
| 80 | +We want to avoid guessing the extension, as this would require require a big overhead. |
| 81 | + |
| 82 | +Example: |
| 83 | + |
| 84 | +```typescript |
| 85 | +import { f, SomeType, SomeInterface } from "./module.js"; |
| 86 | +``` |
| 87 | + |
| 88 | +This would require Node.js to search on the file system the existance of `module.js` and `module.ts` files, and if they exist, load them. |
| 89 | +The `tsconfig.json` option `allowImportingTsExtensions` may help provide compatibility with other tools. |
| 90 | + |
| 91 | +#### Performance |
| 92 | + |
| 93 | +We should keep in mind that this feature should be fast, and not add a big overhead to the startup time of Node.js. |
| 94 | +We want to be faster that external loaders, without bloating the Node.js binary. |
| 95 | +Given that the initial implementation uses [@swc/wasm-typescript](https://swc.rs/docs/references/wasm-typescript), a wasm implementation of `@swc` we should consider moving to a native implementation. |
| 96 | +This should be a goal as performance is critical. |
| 97 | + |
| 98 | +#### REPL |
| 99 | + |
| 100 | +The REPL should support TypeScript, and the `--experimental-strip-types` flag should be supported. |
0 commit comments