Skip to content

Commit c09ce24

Browse files
ryan-naumaneps1lon
andauthored
fix: improve tsconfig extends checks (#61413)
Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
1 parent 3fa9cb7 commit c09ce24

File tree

3 files changed

+134
-12
lines changed

3 files changed

+134
-12
lines changed

packages/next/src/lib/typescript/writeConfigurationDefaults.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,33 @@ export async function writeConfigurationDefaults(
223223
)
224224
)
225225
} else if (hasAppDir && !rawConfig.include.includes(nextAppTypes)) {
226-
userTsConfig.include.push(nextAppTypes)
227-
suggestedActions.push(
228-
cyan('include') + ' was updated to add ' + bold(`'${nextAppTypes}'`)
229-
)
226+
if (!Array.isArray(userTsConfig.include)) {
227+
userTsConfig.include = []
228+
}
229+
// rawConfig will resolve all extends and include paths (ex: tsconfig.json, tsconfig.base.json, etc.)
230+
// if it doesn't match userTsConfig then update the userTsConfig to add the
231+
// rawConfig's includes in addition to nextAppTypes
232+
if (
233+
rawConfig.include.length !== userTsConfig.include.length ||
234+
JSON.stringify(rawConfig.include.sort()) !==
235+
JSON.stringify(userTsConfig.include.sort())
236+
) {
237+
userTsConfig.include.push(...rawConfig.include, nextAppTypes)
238+
suggestedActions.push(
239+
cyan('include') +
240+
' was set to ' +
241+
bold(
242+
`[${[...rawConfig.include, nextAppTypes]
243+
.map((i) => `'${i}'`)
244+
.join(', ')}]`
245+
)
246+
)
247+
} else {
248+
userTsConfig.include.push(nextAppTypes)
249+
suggestedActions.push(
250+
cyan('include') + ' was updated to add ' + bold(`'${nextAppTypes}'`)
251+
)
252+
}
230253
}
231254

232255
// Enable the Next.js typescript plugin.
@@ -270,14 +293,13 @@ export async function writeConfigurationDefaults(
270293
)
271294
}
272295

273-
// If `strict` is set to `false` or `strictNullChecks` is set to `false`,
296+
// If `strict` is set to `false` and `strictNullChecks` is set to `false`,
274297
// then set `strictNullChecks` to `true`.
275298
if (
276299
hasPagesDir &&
277300
hasAppDir &&
278-
userTsConfig.compilerOptions &&
279-
!userTsConfig.compilerOptions.strict &&
280-
!('strictNullChecks' in userTsConfig.compilerOptions)
301+
!tsOptions.strict &&
302+
!('strictNullChecks' in tsOptions)
281303
) {
282304
userTsConfig.compilerOptions.strictNullChecks = true
283305
suggestedActions.push(

test/integration/tsconfig-verifier/test/index.test.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,7 @@ import path from 'path'
695695
"{
696696
"extends": "./tsconfig.base.json",
697697
"compilerOptions": {
698-
"target": "ES2017",
699-
"strictNullChecks": true
698+
"target": "ES2017"
700699
}
701700
}
702701
"
@@ -764,8 +763,7 @@ import path from 'path'
764763
"extends": "./tsconfig.base.json",
765764
"compilerOptions": {
766765
"target": "ES2017",
767-
"incremental": true,
768-
"strictNullChecks": true
766+
"incremental": true
769767
}
770768
}
771769
"
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* eslint-env jest */
2+
import fs from 'fs-extra'
3+
import { join } from 'path'
4+
import { writeConfigurationDefaults } from 'next/dist/lib/typescript/writeConfigurationDefaults'
5+
import * as ts from 'typescript'
6+
7+
const fixtureDir = join(__dirname, 'fixtures/config-ts')
8+
const tsconfigFile = join(fixtureDir, 'tsconfig.json')
9+
const tsconfigBaseFile = join(fixtureDir, 'tsconfig.base.json')
10+
const distDir = '.next'
11+
const nextAppTypes = `${distDir}/types/**/*.ts`
12+
13+
describe('tsconfig.base.json', () => {
14+
beforeEach(async () => {
15+
await fs.ensureDir(fixtureDir)
16+
})
17+
afterEach(async () => {
18+
await fs.remove(tsconfigFile)
19+
await fs.remove(tsconfigBaseFile)
20+
})
21+
22+
describe('appDir', () => {
23+
it('should support empty includes when base provides it', async () => {
24+
const include = ['**/*.ts', '**/*.tsx', nextAppTypes]
25+
const content = {
26+
extends: './tsconfig.base.json',
27+
}
28+
const baseContent = {
29+
include,
30+
}
31+
32+
await fs.writeFile(tsconfigFile, JSON.stringify(content, null, 2))
33+
await fs.writeFile(tsconfigBaseFile, JSON.stringify(baseContent, null, 2))
34+
35+
await expect(
36+
writeConfigurationDefaults(ts, tsconfigFile, false, true, distDir, true)
37+
).resolves.not.toThrow()
38+
39+
const output = await fs.readFile(tsconfigFile, 'utf8')
40+
const parsed = JSON.parse(output)
41+
42+
expect(parsed.include).toBeUndefined()
43+
})
44+
45+
it('should replace includes when base is missing appTypes', async () => {
46+
const include = ['**/*.ts', '**/*.tsx']
47+
const content = {
48+
extends: './tsconfig.base.json',
49+
}
50+
const baseContent = {
51+
include,
52+
}
53+
54+
await fs.writeFile(tsconfigFile, JSON.stringify(content, null, 2))
55+
await fs.writeFile(tsconfigBaseFile, JSON.stringify(baseContent, null, 2))
56+
57+
await expect(
58+
writeConfigurationDefaults(ts, tsconfigFile, false, true, distDir, true)
59+
).resolves.not.toThrow()
60+
61+
const output = await fs.readFile(tsconfigFile, 'utf8')
62+
const parsed = JSON.parse(output)
63+
64+
expect(parsed.include.sort()).toMatchInlineSnapshot(`
65+
[
66+
"**/*.ts",
67+
"**/*.tsx",
68+
".next/types/**/*.ts",
69+
]
70+
`)
71+
})
72+
73+
it('should not add strictNullChecks if base provides it', async () => {
74+
const content = {
75+
extends: './tsconfig.base.json',
76+
}
77+
78+
const baseContent = {
79+
compilerOptions: {
80+
strictNullChecks: true,
81+
strict: true,
82+
},
83+
}
84+
85+
await fs.writeFile(tsconfigFile, JSON.stringify(content, null, 2))
86+
await fs.writeFile(tsconfigBaseFile, JSON.stringify(baseContent, null, 2))
87+
88+
await writeConfigurationDefaults(
89+
ts,
90+
tsconfigFile,
91+
false,
92+
true,
93+
distDir,
94+
true
95+
)
96+
const output = await fs.readFile(tsconfigFile, 'utf8')
97+
const parsed = JSON.parse(output)
98+
99+
expect(parsed.compilerOptions.strictNullChecks).toBeUndefined()
100+
})
101+
})
102+
})

0 commit comments

Comments
 (0)