diff --git a/docs/guide/cli-generated.md b/docs/guide/cli-generated.md index db20e2726..93cb69c96 100644 --- a/docs/guide/cli-generated.md +++ b/docs/guide/cli-generated.md @@ -791,6 +791,13 @@ Allow JavaScript files to be typechecked. By default takes the value from tsconf Ignore type errors from source files +### typecheck.build + +- **CLI:** `--typecheck.build` +- **Config:** [typecheck.build](/config/typecheck#typecheck-build) + +Use TypeScript build mode + ### typecheck.tsconfig - **CLI:** `--typecheck.tsconfig ` diff --git a/packages/vitest/src/node/cli/cli-config.ts b/packages/vitest/src/node/cli/cli-config.ts index ccd6f76cb..9878b64e3 100644 --- a/packages/vitest/src/node/cli/cli-config.ts +++ b/packages/vitest/src/node/cli/cli-config.ts @@ -726,6 +726,9 @@ export const cliOptionsConfig: VitestCLIOptions = { ignoreSourceErrors: { description: 'Ignore type errors from source files', }, + build: { + description: 'Use TypeScript build mode', + }, tsconfig: { description: 'Path to a custom tsconfig file', argument: '', diff --git a/packages/vitest/src/node/types/config.ts b/packages/vitest/src/node/types/config.ts index fe77fb756..020384634 100644 --- a/packages/vitest/src/node/types/config.ts +++ b/packages/vitest/src/node/types/config.ts @@ -1014,6 +1014,10 @@ export interface TypecheckConfig { * Do not fail, if Vitest found errors outside the test files. */ ignoreSourceErrors?: boolean + /** + * Use TypeScript build mode. + */ + build?: boolean /** * Path to tsconfig, relative to the project root. */ diff --git a/packages/vitest/src/typecheck/typechecker.ts b/packages/vitest/src/typecheck/typechecker.ts index 55340f10e..a7a180f60 100644 --- a/packages/vitest/src/typecheck/typechecker.ts +++ b/packages/vitest/src/typecheck/typechecker.ts @@ -294,16 +294,25 @@ export class Typechecker { const { root, watch, typecheck } = this.project.config const args = [ - '--noEmit', '--pretty', 'false', - '--incremental', - '--tsBuildInfoFile', - join( - process.versions.pnp ? join(os.tmpdir(), this.project.hash) : distDir, - 'tsconfig.tmp.tsbuildinfo', - ), ] + + if (typecheck.build) { + args.unshift('--build') + } + else { + args.push( + '--noEmit', + '--incremental', + '--tsBuildInfoFile', + join( + process.versions.pnp ? join(os.tmpdir(), this.project.hash) : distDir, + 'tsconfig.tmp.tsbuildinfo', + ), + ) + } + // use builtin watcher because it's faster if (watch) { args.push('--watch') @@ -312,7 +321,11 @@ export class Typechecker { args.push('--allowJs', '--checkJs') } if (typecheck.tsconfig) { - args.push('-p', resolve(root, typecheck.tsconfig)) + if (!typecheck.build) { + args.push('-p') + } + + args.push(resolve(root, typecheck.tsconfig)) } this._output = '' this._startTime = performance.now() diff --git a/test/e2e/project-references/.gitignore b/test/e2e/project-references/.gitignore new file mode 100644 index 000000000..c832a6518 --- /dev/null +++ b/test/e2e/project-references/.gitignore @@ -0,0 +1 @@ +!/packages/project-b/node_modules \ No newline at end of file diff --git a/test/e2e/project-references/package.json b/test/e2e/project-references/package.json new file mode 100644 index 000000000..e97df9fd2 --- /dev/null +++ b/test/e2e/project-references/package.json @@ -0,0 +1,14 @@ +{ + "name": "@vitest/test-integration-project-references", + "type": "module", + "private": true, + "scripts": { + "test": "(rm -rf packages/*/dist || true) && vitest run" + }, + "devDependencies": { + "vitest": "workspace:*" + }, + "workspaces": [ + "packages/*" + ] +} diff --git a/test/e2e/project-references/packages/project-a/package.json b/test/e2e/project-references/packages/project-a/package.json new file mode 100644 index 000000000..0662b8584 --- /dev/null +++ b/test/e2e/project-references/packages/project-a/package.json @@ -0,0 +1,6 @@ +{ + "name": "project-a", + "type": "module", + "private": true, + "exports": "./src/index.ts" +} diff --git a/test/e2e/project-references/packages/project-a/src/index.ts b/test/e2e/project-references/packages/project-a/src/index.ts new file mode 100644 index 000000000..322d9b3ea --- /dev/null +++ b/test/e2e/project-references/packages/project-a/src/index.ts @@ -0,0 +1,2 @@ +export type A = number +export const a: A = 1 diff --git a/test/e2e/project-references/packages/project-a/tsconfig.json b/test/e2e/project-references/packages/project-a/tsconfig.json new file mode 100644 index 000000000..c275baf43 --- /dev/null +++ b/test/e2e/project-references/packages/project-a/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "composite": true, + "target": "esnext", + "lib": ["DOM", "ESNext"], + "module": "nodenext", + "types": [], + "strict": true, + "declaration": true, + "declarationMap": true, + "outDir": "dist", + "sourceMap": true, + "verbatimModuleSyntax": true, + "skipLibCheck": false + }, + "files": ["src/index.ts"] +} diff --git a/test/e2e/project-references/packages/project-b/node_modules/project-a b/test/e2e/project-references/packages/project-b/node_modules/project-a new file mode 120000 index 000000000..c4bb4d086 --- /dev/null +++ b/test/e2e/project-references/packages/project-b/node_modules/project-a @@ -0,0 +1 @@ +../../project-a \ No newline at end of file diff --git a/test/e2e/project-references/packages/project-b/package.json b/test/e2e/project-references/packages/project-b/package.json new file mode 100644 index 000000000..31aaefa05 --- /dev/null +++ b/test/e2e/project-references/packages/project-b/package.json @@ -0,0 +1,8 @@ +{ + "name": "project-b", + "type": "module", + "private": true, + "dependencies": { + "project-a": "workspace:*" + } +} diff --git a/test/e2e/project-references/packages/project-b/src/b.test-d.ts b/test/e2e/project-references/packages/project-b/src/b.test-d.ts new file mode 100644 index 000000000..107b57da5 --- /dev/null +++ b/test/e2e/project-references/packages/project-b/src/b.test-d.ts @@ -0,0 +1,9 @@ +import type { A } from 'project-a' +import { a } from 'project-a' +import { describe, expectTypeOf, it } from 'vitest' + +describe('Import types from project references', () => { + it('should import value and type from project references', () => { + expectTypeOf(a).toEqualTypeOf() + }) +}) diff --git a/test/e2e/project-references/packages/project-b/tsconfig.json b/test/e2e/project-references/packages/project-b/tsconfig.json new file mode 100644 index 000000000..e9848638b --- /dev/null +++ b/test/e2e/project-references/packages/project-b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "composite": true, + "target": "esnext", + "lib": ["DOM", "ESNext"], + "module": "nodenext", + "types": [], + "strict": true, + "declaration": true, + "declarationMap": true, + "outDir": "dist", + "sourceMap": true, + "verbatimModuleSyntax": true, + "skipLibCheck": false + }, + "references": [ + { "path": "../project-a" } + ], + "files": ["src/b.test-d.ts"], + "exclude": ["node_modules"] +} diff --git a/test/e2e/project-references/tsconfig.json b/test/e2e/project-references/tsconfig.json new file mode 100644 index 000000000..1b91001e9 --- /dev/null +++ b/test/e2e/project-references/tsconfig.json @@ -0,0 +1,7 @@ +{ + "references": [ + { "path": "./packages/project-a" }, + { "path": "./packages/project-b" } + ], + "include": [] +} diff --git a/test/e2e/project-references/vitest.config.ts b/test/e2e/project-references/vitest.config.ts new file mode 100644 index 000000000..276c63a51 --- /dev/null +++ b/test/e2e/project-references/vitest.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + projects: [{ + test: { + name: 'project-b', + dir: 'packages/project-b', + typecheck: { + enabled: true, + build: true, + }, + }, + }], + }, +})