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 configuration flags to disable integrated type checker #9138

Merged
merged 10 commits into from
Oct 28, 2019
12 changes: 12 additions & 0 deletions packages/next/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2316,6 +2316,18 @@ 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 all TypeScript errors during dev and prevents application build if any are detected.
kachkaev marked this conversation as resolved.
Show resolved Hide resolved
> If you don't want to leverage this behaviour and prefer to do type checks manually, set the following option in your `next.config.js`:
>
> ```js
> // next.config.js
> module.exports = {
> typescript: {
> transpileOnly: 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.
Expand Down
2 changes: 1 addition & 1 deletion packages/next/build/output/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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...')
kachkaev marked this conversation as resolved.
Show resolved Hide resolved
return
}

Expand Down
3 changes: 3 additions & 0 deletions packages/next/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ export default async function getBaseWebpackConfig(
const useTypeScript = Boolean(
typeScriptPath && (await fileExists(tsConfigPath))
)
const typescriptTranspileOnly =
config.typescript && config.typescript.transpileOnly

const resolveConfig = {
// Disable .mjs for node_modules bundling
Expand Down Expand Up @@ -839,6 +841,7 @@ export default async function getBaseWebpackConfig(
}),
!isServer &&
useTypeScript &&
!typescriptTranspileOnly &&
kachkaev marked this conversation as resolved.
Show resolved Hide resolved
new ForkTsCheckerWebpackPlugin(
PnpWebpackPlugin.forkTsCheckerOptions({
typescript: typeScriptPath,
Expand Down
4 changes: 3 additions & 1 deletion packages/next/server/hot-reloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 typescriptTranspileOnly =
this.config.typescript && this.config.typescript.transpileOnly

watchCompilers(
multiCompiler.compilers[0],
multiCompiler.compilers[1],
useTypeScript,
useTypeScript && !typescriptTranspileOnly,
({ errors, warnings }) => this.send('typeChecked', { errors, warnings })
)

Expand Down
5 changes: 5 additions & 0 deletions test/integration/typescript-transpileonly/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
typescript: {
transpileOnly: true
}
}
2 changes: 2 additions & 0 deletions test/integration/typescript-transpileonly/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Below type error is intentional, it helps check typescript.transpileOnly flag in next.config.js
export default (): boolean => 'Index page'
56 changes: 56 additions & 0 deletions test/integration/typescript-transpileonly/test/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* eslint-env jest */
/* global jasmine */
import { join } from 'path'
import cheerio from 'cheerio'
import {
renderViaHTTP,
nextBuild,
findPort,
launchApp,
killApp
} from 'next-test-utils'

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)
return cheerio.load(html)
}

describe('TypeScript with transpileOnly flag', () => {
describe('default behavior', () => {
beforeAll(async () => {
output = ''
appPort = await findPort()
app = await launchApp(appDir, appPort, {
onStdout: handleOutput,
onStderr: handleOutput
})
})
afterAll(() => killApp(app))

it('should render the page despite type errors', async () => {
const $ = await get$('/')
expect($('body').text()).toMatch(/Index page/)
})

it('should not report type checking to stdout', async () => {
expect(output).not.toContain('waiting for typecheck results...')
expect(output).not.toContain("is not assignable to type 'boolean'")
})
})

it('should compile the app despite type errors', async () => {
const output = await nextBuild(appDir, [], { stdout: true })
expect(output.stdout).toMatch(/Compiled successfully/)
})
})
19 changes: 19 additions & 0 deletions test/integration/typescript-transpileonly/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"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"]
}
15 changes: 14 additions & 1 deletion test/integration/typescript/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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))

Expand All @@ -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...')
kachkaev marked this conversation as resolved.
Show resolved Hide resolved
})

it('should not fail to render when an inactive page has an error', async () => {
await killApp(app)
let evilFile = join(appDir, 'pages', 'evil.tsx')
Expand Down