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

Add warning when TypeScript's 'target' option is changed from default #43582

4 changes: 4 additions & 0 deletions errors/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,10 @@
{
"title": "fast-refresh-reload",
"path": "/errors/fast-refresh-reload.md"
},
{
"title": "tsconfig-target-option",
"path": "/errors/tsconfig-target-option.md"
}
]
}
Expand Down
20 changes: 20 additions & 0 deletions errors/tsconfig-target-option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# TypeScript's Target Option

#### Why This Warning Occurred

You've changed the `target` option in `tsconfig.json` from the default `es5` to a different value.

Next.js doesn't use [`tsc`](https://www.typescriptlang.org/docs/handbook/compiler-options.html) to compile TypeScript to JavaScript, so the `target` option has no effect on the output.
You should not expect to see any changes in your output code after changing this option.
styfle marked this conversation as resolved.
Show resolved Hide resolved

#### Possible Ways to Fix It

If you want to target specific browsers or features, Next.js supports [Browserslist](https://browsersl.ist/)
configuration in your `package.json` file.

So instead of changing TypeScript's `target` option, you should specify a Browserslist configuration
and Next.js will build your code accordingly.

### Useful Links

- [Supported Browsers and Features](https://nextjs.org/docs/basic-features/supported-browsers-features)
13 changes: 13 additions & 0 deletions packages/next/lib/typescript/writeConfigurationDefaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import chalk from 'next/dist/compiled/chalk'
import * as CommentJson from 'next/dist/compiled/comment-json'
import semver from 'next/dist/compiled/semver'
import os from 'os'
import * as Log from '../../build/output/log'
import type { CompilerOptions } from 'typescript'
import { getTypeScriptConfiguration } from './getTypeScriptConfiguration'

Expand Down Expand Up @@ -113,6 +114,18 @@ export async function writeConfigurationDefaults(
const { options: tsOptions, raw: rawConfig } =
await getTypeScriptConfiguration(ts, tsConfigPath, true)

if (tsOptions.target && tsOptions.target !== ts.ScriptTarget.ES5) {
Log.warn(
`The ${chalk.bold('target')} option in your ${chalk.bold(
'tsconfig.json'
)} is changed from the default '${chalk.bold('es5')}' to '${chalk.bold(
ts.ScriptTarget[tsOptions.target]
)}',` +
` which has no effect. Please use a Browserslist configuration instead.` +
` Read more: https://nextjs.org/docs/messages/tsconfig-target-option`
)
}

const userTsConfigContent = await fs.readFile(tsConfigPath, {
encoding: 'utf8',
})
Expand Down
33 changes: 33 additions & 0 deletions test/development/correct-tsconfig-defaults/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,37 @@ describe('correct tsconfig.json defaults', () => {
await next.stop()
}
})

it('should not warn if `target` is unchanged', async () => {
try {
expect(
await next.readFile('tsconfig.json').catch(() => false)
).toBeTruthy()

await next.start()

expect(next.cliOutput).not.toContain('tsconfig-target-option')
} finally {
await next.stop()
}
})

it('should warn if `target` is changed', async () => {
try {
expect(
await next.readFile('tsconfig.json').catch(() => false)
).toBeTruthy()

// Change target option to a non-default value
const tsconfig = JSON.parse(await next.readFile('tsconfig.json'))
tsconfig.compilerOptions.target = 'ES2022'
await next.patchFile('tsconfig.json', JSON.stringify(tsconfig))

await next.start()

expect(next.cliOutput).toContain('tsconfig-target-option')
} finally {
await next.stop()
}
})
})