Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate tsconfig #5519

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 6 additions & 25 deletions docusaurus/docs/adding-typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,12 @@ Recent versions of [TypeScript](https://www.typescriptlang.org/) work with Creat
To add TypeScript to a Create React App project, follow these steps:

1. Run `npm install --save typescript @types/react @types/react-dom @types/jest` (or `yarn add typescript @types/react @types/react-dom @types/jest`).
2. Rename the `.js` files you want to convert: use `.tsx` if they use JSX or `.ts` if not (e.g. `git mv src/index.js src/index.tsx`).

3. Create a [`tsconfig.json` file](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) at the root directory with the following content:

```json
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"moduleResolution": "node",
"lib": ["esnext", "dom", "dom.iterable"],
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"jsx": "preserve",
"noEmit": true,
"skipLibCheck": true,
"strict": true
},
"include": ["src"]
}
```

4. Copy [loaders.d.ts](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/src/loaders.d.ts) from the template to your `src` directory.

2. Rename the `.js` files you want to convert: use `.tsx` if they use JSX or `.ts` if not (e.g. `git mv src/index.js src/index.tsx`). **Note that the entrypoint must be named either `src/index.ts` or `src/index.tsx` to enable TypeScript in your project.**

3. Copy [loaders.d.ts](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/src/loaders.d.ts) from the template to your `src` directory.

4. Run `npm start` (or `yarn start`) and a `tsconfig.json` file will be generated and placed at the root of your project with the appropriate config required by Create React App.

Type errors will show up in the same console as the build one.

Expand Down
97 changes: 93 additions & 4 deletions packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,33 @@
const chalk = require('chalk');
const fs = require('fs');
const resolve = require('resolve');
const path = require('path');
const paths = require('../../config/paths');

function verifyTypeScriptSetup() {
if (!fs.existsSync(paths.appTsConfig)) {
if (!paths.appIndexJs.endsWith('.ts') || !paths.appIndexJs.endsWith('.tsx')) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be &&?

Also just fyi that the index file is not required to be .ts or .tsx on typescript projects.

return;
}

if (!fs.existsSync(paths.appTsConfig)) {
fs.writeFileSync(
paths.appTsConfig,
JSON.stringify(defaultTSConfig, null, 2),
'utf-8'
);
}

const isYarn = fs.existsSync(paths.yarnLockFile);

// Ensure typescript is installed
try {
resolve.sync('typescript', {
function findTypeScript() {
return resolve.sync('typescript', {
basedir: paths.appNodeModules,
});
}

// Ensure typescript is installed
try {
findTypeScript();
} catch (_) {
console.error(
chalk.red(
Expand Down Expand Up @@ -53,6 +66,82 @@ function verifyTypeScriptSetup() {
console.error();
process.exit(1);
}

const ts = require(findTypeScript());
// Read the contents of the config file
// Note that this function doesn't merge in "extends" config
const result = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile);

if (result.error) {
console.error(
'There was an error while trying to parse your ' +
chalk.cyan('tsconfig.json') +
' file. Please ensure the contents are valid.'
);
console.error();
console.error(chalk.red(result.error.messageText));
console.error();
process.exit(1);
}

// Parse json, merge config extending others, ...
const parsedResult = ts.parseJsonConfigFileContent(
result.config,
ts.sys,
// TODO: paths.appPath is '/packages/react-scripts' when developing. Can we do something cleaner?
// A root directory to resolve relative path entries in the config
path.resolve(paths.appSrc, '..')
);

if (parsedResult.errors.length) {
console.error(
'There were errors while trying to parse your ' +
chalk.cyan('tsconfig.json') +
' file. Please ensure the contents are valid.'
);
console.error();

for (const error of parsedResult.errors) {
console.error(chalk.red(error.messageText));
console.error();
}

process.exit(1);
}

const compilerOptions = parsedResult.options;

if (compilerOptions.isolatedModules !== true) {
console.error(
'We detected that ' +
chalk.bold('isolatedModules') +
' was not set to ' +
chalk.bold('true') +
' in your ' +
chalk.cyan('tsconfig.json') +
' file. Please update your configuration and try again.'
);
console.error();
process.exit(1);
}
}

module.exports = verifyTypeScriptSetup;

const defaultTSConfig = {
compilerOptions: {
target: 'es5',
module: 'esnext',
moduleResolution: 'node',
lib: ['esnext', 'dom', 'dom.iterable'],
allowJs: true,
allowSyntheticDefaultImports: true,
esModuleInterop: true,
isolatedModules: true,
jsx: 'preserve',
noEmit: true,
skipLibCheck: true,
strict: true,
},
include: ['src'],
};