Description
Is your proposal related to a problem?
I'm using create-react-app for my React workshops. Each project has an exercise file (the unfinished code) and a final file (the finished code). I'm rewriting them all to TypeScript. I don't want to enable strict mode for the exercise files because it can be difficult for people new to TypeScript. However I do want the final version of the exercise to be type checked with strict mode (for my own sake).
Having different configs for different files in a project can be accomplished using project references configuration. Here's what I've done to make this "work": kentcdodds/react-fundamentals@84eb9ed
tsconfig.json
{
"files": [],
"references": [
{"path": "config/tsconfig.exercise.json"},
{"path": "config/tsconfig.final.json"}
]
}
config/tsconfig.exercise.json
{
"extends": "./tsconfig.shared.json",
"include": ["../src/exercise/"],
"compilerOptions": {
"strict": false
}
}
config/tsconfig.final.json
{
"extends": "./tsconfig.shared.json",
"exclude": ["../src/exercise/"],
"include": ["../src"],
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true
}
}
config/tsconfig.shared.json
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"noFallthroughCasesInSwitch": true
}
}
Running tsc -b
will typecheck all the files with the expected configuration.
However, as soon as I run react-scripts start
, my tsconfig.json
gets changed:
{
"files": [],
"references": [
{
"path": "config/tsconfig.exercise.json"
},
{
"path": "config/tsconfig.final.json"
}
],
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
With those changes, when I try to run tsc
(or tsc -b
), I get several errors, for example:
tsconfig.json:4:5 - error TS6306: Referenced project '/Users/kentcdodds/code/epic-react/react-fundamentals/config/tsconfig.exercise.json' must have setting "composite": true.
4 {
~
5 "path": "config/tsconfig.exercise.json"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 },
~~~~~
tsconfig.json:7:5 - error TS6310: Referenced project '/Users/kentcdodds/code/epic-react/react-fundamentals/config/tsconfig.final.json' may not disable emit.
By setting "noEmit": false
and "composite": true
to the config/tsconfig.shared.json
, I get a little further, but can't get rid of this error:
error TS6305: Output file '/Users/kentcdodds/code/epic-react/react-fundamentals/src/final/07.extra-3.d.ts' has not been built from source file '/Users/kentcdodds/code/epic-react/react-fundamentals/src/final/07.extra-3.tsx'.
The file is in the program because:
Matched by include pattern 'src' in '/Users/kentcdodds/code/epic-react/react-fundamentals/tsconfig.json'
tsconfig.json:33:5
33 "src"
~~~~~
File is matched by include pattern specified here.
I've tried all combinations of options I can think of and nothing I can think of will make TypeScript happy + accomplish my goal of having a different config for different files in my create-react-app project.
Describe the solution you'd like
I would like support for references
directly. I did notice ts-loader's page on references.
Short of that, I would be happy with an environment variable (similar to SKIP_PREFLIGHT_CHECK
) which opts-out of updating the tsconfig.json
and just trusts that the config works as-is.
Describe alternatives you've considered
I've thought about switching off of create-react-app or using one of the off-shoot projects that are flexible, but I'd really prefer to not do that.
Additional context
I think I've said everything that needs to be said 😅