提交 ad2a3d65 编写于 作者: A Alexander Kachkaev 提交者: Joe Haddad

Add configuration flags to disable integrated type checker (#9138)

* Add a configuration flag to disable integrated type checker

* Add tests for typescript-transpileonly

* Restore removed argument

* Make output more coherent

* Split transpileOnly into ignoreDevErrors and ignoreBuildErrors

* Minor stylistic change
上级 2d9f1991
......@@ -2316,6 +2316,22 @@ To learn more about TypeScript checkout its [documentation](https://www.typescri
> **Note**: Next.js does not enable TypeScript's `strict` mode by default.
> When you feel comfortable with TypeScript, you may turn this option on in your `tsconfig.json`.
> **Note**: By default, Next.js reports TypeScript errors during development for pages you are actively working on.
> TypeScript errors for inactive pages do not block the development process.
> Trying to run `next build` for an app that has TypeScript errors on any page will fail.
>
> If you don't want to leverage this behavior and prefer to do type checks manually, set the following options in your `next.config.js`:
>
> ```js
> // next.config.js
> module.exports = {
> typescript: {
> ignoreDevErrors: true,
> ignoreBuildErrors: true,
> },
> }
> ```
### Exported types
Next.js provides `NextPage` type that can be used for pages in the `pages` directory. `NextPage` adds definitions for [`getInitialProps`](#fetching-data-and-component-lifecycle) so that it can be used without any extra typing needed.
......
......@@ -78,7 +78,7 @@ store.subscribe(state => {
}
if (state.typeChecking) {
Log.info('bundled successfully, waiting for typecheck results ...')
Log.info('bundled successfully, waiting for typecheck results...')
return
}
......
......@@ -126,6 +126,9 @@ export default async function getBaseWebpackConfig(
const useTypeScript = Boolean(
typeScriptPath && (await fileExists(tsConfigPath))
)
const ignoreTypeScriptErrors = dev
? config.typescript && config.typescript.ignoreDevErrors
: config.typescript && config.typescript.ignoreBuildErrors
const resolveConfig = {
// Disable .mjs for node_modules bundling
......@@ -845,6 +848,7 @@ export default async function getBaseWebpackConfig(
}),
!isServer &&
useTypeScript &&
!ignoreTypeScriptErrors &&
new ForkTsCheckerWebpackPlugin(
PnpWebpackPlugin.forkTsCheckerOptions({
typescript: typeScriptPath,
......
......@@ -349,11 +349,13 @@ export default class HotReloader {
async prepareBuildTools(multiCompiler: webpack.MultiCompiler) {
const tsConfigPath = join(this.dir, 'tsconfig.json')
const useTypeScript = await fileExists(tsConfigPath)
const ignoreTypeScriptErrors =
this.config.typescript && this.config.typescript.ignoreDevErrors
watchCompilers(
multiCompiler.compilers[0],
multiCompiler.compilers[1],
useTypeScript,
useTypeScript && !ignoreTypeScriptErrors,
({ errors, warnings }) => this.send('typeChecked', { errors, warnings })
)
......
// Below type error is intentional, it helps check typescript → ignoreDevErrors / ignoreBuildErrors flags in next.config.js
export default (): boolean => 'Index page'
/* eslint-env jest */
/* global jasmine */
import { join } from 'path'
import {
renderViaHTTP,
nextBuild,
findPort,
launchApp,
killApp,
File
} from 'next-test-utils'
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
const appDir = join(__dirname, '..')
const nextConfigFile = new File(join(appDir, 'next.config.js'))
describe('TypeScript with error handling options', () => {
for (const ignoreDevErrors of [false, true]) {
for (const ignoreBuildErrors of [false, true]) {
describe(`ignoreDevErrors: ${ignoreDevErrors}, ignoreBuildErrors: ${ignoreBuildErrors}`, () => {
beforeAll(() => {
const nextConfig = {
typescript: { ignoreDevErrors, ignoreBuildErrors }
}
nextConfigFile.replace('{}', JSON.stringify(nextConfig))
})
afterAll(() => {
nextConfigFile.restore()
})
it(
ignoreDevErrors
? 'Next renders the page in dev despite type errors'
: 'Next dev does not render the page in dev because of type errors',
async () => {
let app
let output = ''
try {
const appPort = await findPort()
app = await launchApp(appDir, appPort, {
onStdout: msg => (output += msg),
onStderr: msg => (output += msg)
})
await renderViaHTTP(appPort, '')
if (ignoreDevErrors) {
expect(output).not.toContain('waiting for typecheck results...')
expect(output).not.toContain("not assignable to type 'boolean'")
} else {
expect(output).toContain('waiting for typecheck results...')
expect(output).toContain("not assignable to type 'boolean'")
}
} finally {
await killApp(app)
}
}
)
it(
ignoreBuildErrors
? 'Next builds the application despite type errors'
: 'Next fails to build the application despite type errors',
async () => {
const { stdout, stderr } = await nextBuild(appDir, [], {
stdout: true,
stderr: true
})
if (ignoreBuildErrors) {
expect(stdout).toContain('Compiled successfully')
expect(stderr).not.toContain('Failed to compile.')
expect(stderr).not.toContain("not assignable to type 'boolean'")
} else {
expect(stdout).not.toContain('Compiled successfully')
expect(stderr).toContain('Failed to compile.')
expect(stderr).toContain("not assignable to type 'boolean'")
}
}
)
})
}
}
})
{
"compilerOptions": {
"esModuleInterop": true,
"module": "esnext",
"jsx": "preserve",
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true
},
"exclude": ["node_modules"],
"include": ["next-env.d.ts", "pages"]
}
......@@ -17,6 +17,11 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
const appDir = join(__dirname, '..')
let appPort
let app
let output
const handleOutput = msg => {
output += msg
}
async function get$ (path, query) {
const html = await renderViaHTTP(appPort, path, query)
......@@ -26,8 +31,12 @@ async function get$ (path, query) {
describe('TypeScript Features', () => {
describe('default behavior', () => {
beforeAll(async () => {
output = ''
appPort = await findPort()
app = await launchApp(appDir, appPort)
app = await launchApp(appDir, appPort, {
onStdout: handleOutput,
onStderr: handleOutput
})
})
afterAll(() => killApp(app))
......@@ -36,6 +45,10 @@ describe('TypeScript Features', () => {
expect($('body').text()).toMatch(/Hello World/)
})
it('should report type checking to stdout', async () => {
expect(output).toContain('waiting for typecheck results...')
})
it('should not fail to render when an inactive page has an error', async () => {
await killApp(app)
let evilFile = join(appDir, 'pages', 'evil.tsx')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册