Skip to content

Commit f6a1235

Browse files
committed
Use TS to resolve tsconfig extends
1 parent 3c11efe commit f6a1235

File tree

1 file changed

+58
-22
lines changed

1 file changed

+58
-22
lines changed

packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,6 @@ function writeJson(fileName, object) {
1919
fs.writeFileSync(fileName, JSON.stringify(object, null, 2) + os.EOL);
2020
}
2121

22-
const compilerOptions = {
23-
// These are suggested values and will be set when not present in the
24-
// tsconfig.json
25-
target: { suggested: 'es5' },
26-
allowJs: { suggested: true },
27-
skipLibCheck: { suggested: true },
28-
esModuleInterop: { suggested: true },
29-
allowSyntheticDefaultImports: { suggested: true },
30-
strict: { suggested: true },
31-
32-
// These values are required and cannot be changed by the user
33-
module: { value: 'esnext', reason: 'for import() and import/export' },
34-
moduleResolution: { value: 'node', reason: 'to match webpack resolution' },
35-
resolveJsonModule: { value: true, reason: 'to match webpack loader' },
36-
isolatedModules: { value: true, reason: 'implementation limitation' },
37-
noEmit: { value: true },
38-
jsx: { value: 'preserve', reason: 'JSX is compiled by Babel' },
39-
};
40-
4122
function verifyTypeScriptSetup() {
4223
let firstTimeSetup = false;
4324

@@ -86,8 +67,44 @@ function verifyTypeScriptSetup() {
8667
process.exit(1);
8768
}
8869

70+
const compilerOptions = {
71+
// These are suggested values and will be set when not present in the
72+
// tsconfig.json
73+
// 'parsedValue' matches the output value from ts.parseJsonConfigFileContent()
74+
target: {
75+
parsedValue: ts.ScriptTarget.ES5,
76+
suggested: 'es5',
77+
},
78+
allowJs: { suggested: true },
79+
skipLibCheck: { suggested: true },
80+
esModuleInterop: { suggested: true },
81+
allowSyntheticDefaultImports: { suggested: true },
82+
strict: { suggested: true },
83+
84+
// These values are required and cannot be changed by the user
85+
module: {
86+
parsedValue: ts.ModuleKind.ESNext,
87+
value: 'esnext',
88+
reason: 'for import() and import/export',
89+
},
90+
moduleResolution: {
91+
parsedValue: ts.ModuleResolutionKind.NodeJs,
92+
value: 'node',
93+
reason: 'to match webpack resolution',
94+
},
95+
resolveJsonModule: { value: true, reason: 'to match webpack loader' },
96+
isolatedModules: { value: true, reason: 'implementation limitation' },
97+
noEmit: { value: true },
98+
jsx: {
99+
parsedValue: ts.JsxEmit.Preserve,
100+
value: 'preserve',
101+
reason: 'JSX is compiled by Babel',
102+
},
103+
};
104+
89105
const messages = [];
90106
let tsconfig;
107+
let parsedOptions;
91108
try {
92109
const { config, error } = ts.readConfigFile(
93110
paths.appTsConfig,
@@ -99,6 +116,21 @@ function verifyTypeScriptSetup() {
99116
}
100117

101118
tsconfig = config;
119+
120+
// Get TS to parse and resolve any "extends"
121+
// Calling this function also mutates the tsconfig above,
122+
// adding in "include" and "exclude", but the compilerOptions remain untouched
123+
const result = ts.parseJsonConfigFileContent(
124+
config,
125+
ts.sys,
126+
path.dirname(paths.appTsConfig)
127+
);
128+
129+
if (result.errors && result.errors.length) {
130+
throw result.errors[0];
131+
}
132+
133+
parsedOptions = result.options;
102134
} catch (_) {
103135
console.error(
104136
chalk.red.bold(
@@ -116,17 +148,20 @@ function verifyTypeScriptSetup() {
116148
}
117149

118150
for (const option of Object.keys(compilerOptions)) {
119-
const { value, suggested, reason } = compilerOptions[option];
151+
const { parsedValue, value, suggested, reason } = compilerOptions[option];
152+
153+
const valueToCheck = parsedValue === undefined ? value : parsedValue;
154+
120155
if (suggested != null) {
121-
if (tsconfig.compilerOptions[option] === undefined) {
156+
if (parsedOptions[option] === undefined) {
122157
tsconfig.compilerOptions[option] = suggested;
123158
messages.push(
124159
`${chalk.cyan('compilerOptions.' + option)} to be ${chalk.bold(
125160
'suggested'
126161
)} value: ${chalk.cyan.bold(suggested)} (this can be changed)`
127162
);
128163
}
129-
} else if (tsconfig.compilerOptions[option] !== value) {
164+
} else if (parsedOptions[option] !== valueToCheck) {
130165
tsconfig.compilerOptions[option] = value;
131166
messages.push(
132167
`${chalk.cyan('compilerOptions.' + option)} ${chalk.bold(
@@ -137,6 +172,7 @@ function verifyTypeScriptSetup() {
137172
}
138173
}
139174

175+
// tsconfig will have the merged "include" and "exclude" by this point
140176
if (tsconfig.include == null) {
141177
tsconfig.include = ['src'];
142178
messages.push(

0 commit comments

Comments
 (0)