Skip to content

Support for project references #10695

Open
@kentcdodds

Description

@kentcdodds

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 😅

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions