This repository demostrate the behavior of TypeScript module system.
There are may issues about the module system in TypeScript:
- microsoft/TypeScript#50501
- microsoft/TypeScript#50152
- microsoft/TypeScript#50058
- microsoft/TypeScript#50647
- microsoft/TypeScript#48854
- and so on...
This repository tries to answer the following questions:
- How to write your code when using certain settings?
- Does the code compile?
- Is the compile result correct?
- Which setting should you use in different situations?
It is currently tests against TypeScript 5.0.0-dev.20230103
This demo contains multiple test configurations.
Each test configuration contains a specific tsconfig.json
setting:
Test Configuration | moduleResolution |
allowSyntheticDefaultImports |
esModuleInterop |
---|---|---|---|
node | Node |
false |
false |
node-allow | Node |
true |
false |
node-es | Node |
(true) |
true |
node16 | Node16 |
false |
false |
node16-allow | Node16 |
true |
false |
node16-es | Node16 |
(true) |
true |
nodenext | NodeNext |
false |
false |
nodenext-allow | NodeNext |
true |
false |
nodenext-es | NodeNext |
(true) |
true |
Note that when esModuleInterop
is true
, allowSyntheticDefaultImports
will automatically be true
.
Within each test configuration, there are multiple tsconfig.*.json
. One for each module
values as follow:
CommonJS
ES2015
ES2020
ES2022
ESNext
Node16
NodeNext
The other module
values are not tested.
The ES*
code are tested with type: module
under Node.js.
Theoretically, it should be run under browser or use a bundler to bundle them first.
We can improve that in the future.
For now, running them under Node.js with type: module
should be suffice.
Each test project imports multiple packages. Each of the package represents certain scenario.
Within each test configuration, the way to consume each package might be different.
They are adjusted to fit the configuration as much as possible.
When either or both compile and runtime fails, the code is adjusted to make compile pass if possible. This helps to identify any hidden issue where TypeScript says the code is good, but it is not.
Every test file is named with the following format: <package>-<import syntax>.<scope>.ts
For example:
assert-default-as.all.ts
param-case-star.cjs.ts
param-case-star.es.ts
: forES*
param-case-star.es2015.ts
: forES2015
The convention allow us to scope test easily so that it is easier to collect test results.
assert
is a module within Node.js itself.
The type definition comes from @types/node
from DefinitelyTyped.
It utilizes module declaration (i.e. declare module
).
The module is exported with export =
declaration.
assertron@7
is written in TypeScript, and compiled to CommonJS.
Its type definition uses export default
declaration, generated by tsc
.
It also exposes a module
field in package.json
, but that should not affect the test.
It also has a transient dependency on assertion-error
which uses export =
in the type definition.
param-case@1
is written in TypeScript, and compiled to CommonJS.
It exposes CJS with export =
in the type definition.
The type definition is hand-written to match CJS behavior.
It does not use declare module
.
cjs
is a local package that exposes CJS.
Its type definition uses export default
declaration, generated by tsc
.
It does not contain module
field in package.json
.
es-cjs
is a local package that exposes main
in CJS and module
in ES*
format.
It should behaves identical to cjs
for these tests.
It is added for reference.
esm-cjs
is a local package that exposes main
in CJS and exports
in Node*
format.
esm
is a local package that expose exports
in Node*
format.
It does not contain a main
field.
This package does not apply to test configurations that uses moduleResolution: Node
.
The project comes with a tester
cil tool to build the results.
To run everything, run pnpm demo
.
After running demo, a test-result.<typescript-version>.md
will be created in each test project.
You can format the file in VSCode to make it easier to read directly.
If you want to run the demo against a new version,
update the typescript with pnpm up -r typescript@<version>
Furthermore, you can:
pnpm demo [project] --moduleTypes [...]
pnpm demo compile [project] --moduleTypes [...]
pnpm demo runtime [project] --moduleTypes [...]
- referencing a
esm
package which depends oncjs
withexport default
- referencing a
esm
package which depends oncjs
withexport =