diff --git a/e2e/harmony/tsconfig-env-mismatch.e2e.ts b/e2e/harmony/tsconfig-env-mismatch.e2e.ts index b87c34566c61..1f423578c288 100644 --- a/e2e/harmony/tsconfig-env-mismatch.e2e.ts +++ b/e2e/harmony/tsconfig-env-mismatch.e2e.ts @@ -41,7 +41,9 @@ describe('tsconfig env mismatch between check-types and build', function () { before(() => { helper.scopeHelper.setWorkspaceWithRemoteScope(); - // Create permissive tsconfig (no strict mode) + // Create permissive tsconfig (strict mode explicitly off). + // Setting strict explicitly makes the fixture's intent self-documenting and + // independent of any future change to TypeScript's tsconfig defaults. const permissiveTsconfig = JSON.stringify( { compilerOptions: { @@ -55,7 +57,7 @@ describe('tsconfig env mismatch between check-types and build', function () { moduleResolution: 'node', esModuleInterop: true, outDir: './dist', - // No strict mode - permissive + strict: false, }, exclude: ['artifacts', 'public', 'dist', 'node_modules'], }, diff --git a/scopes/typescript/ts-server/ts-server-client.ts b/scopes/typescript/ts-server/ts-server-client.ts index 39540640f476..80874253dd96 100644 --- a/scopes/typescript/ts-server/ts-server-client.ts +++ b/scopes/typescript/ts-server/ts-server-client.ts @@ -66,14 +66,17 @@ export class TsserverClient { onEvent: this.onTsserverEvent.bind(this), }); - this.tsServer - .start() - .then(() => { - this.serverRunning = true; - }) - .catch((err) => { - this.logger.error('TsserverClient.init failed', err); - }); + // Await the server to be ready before issuing any requests, so a start() failure + // (e.g., tsserver writing to stderr) surfaces here rather than producing a write to a + // broken stdin, and so the inferred-project options below are applied to a live server. + await this.tsServer.start(); + this.serverRunning = true; + + // TS 6 flipped the `strict` default from false to true for inferred projects. + // Files outside any tsconfig (e.g., components whose env's tsconfig isn't included + // by the workspace config writer) would otherwise get strict-mode errors that didn't + // surface in TS 5. Pin inferred-project options to the TS 5 default to preserve behavior. + await this.setCompilerOptionsForInferredProjects({ strict: false }); const shouldOpenFiles = this.options.openFilesOnInit !== false; if (this.files.length && shouldOpenFiles) { @@ -296,6 +299,12 @@ export class TsserverClient { return this.tsServer?.request(CommandTypes.Configure, configureArgs); } + private async setCompilerOptionsForInferredProjects( + options: ts.server.protocol.ExternalProjectCompilerOptions + ): Promise { + await this.tsServer?.request(CommandTypes.CompilerOptionsForInferredProjects, { options }); + } + /** * ask tsserver to open a file if it was not opened before. * @param file absolute path of the file diff --git a/scopes/typescript/typescript/typescript.main.runtime.ts b/scopes/typescript/typescript/typescript.main.runtime.ts index 3146deedf61e..14e91e88ea91 100644 --- a/scopes/typescript/typescript/typescript.main.runtime.ts +++ b/scopes/typescript/typescript/typescript.main.runtime.ts @@ -130,6 +130,28 @@ export class TypescriptMain { const configMutator = new TypescriptConfigMutator(options); const transformerContext: TsConfigTransformContext = {}; const afterMutation = runTransformersWithContext(configMutator.clone(), transformers, transformerContext); + // TS 6 flipped several defaults and turned legacy options into hard errors. + // Shipped env tsconfigs must stay valid for TS 5.x consumers, so patch the raw tsconfig + // at runtime when the loaded compiler is actually TS 6+ — preserving TS 5 behavior. + const tsMajor = parseInt(tsModule.version?.split('.')[0] || '0', 10); + const tsconfig = afterMutation.raw.tsconfig; + const compilerOptions = tsconfig?.compilerOptions; + if (tsMajor >= 6 && compilerOptions) { + if (!compilerOptions.ignoreDeprecations) compilerOptions.ignoreDeprecations = '6.0'; + if (compilerOptions.noUncheckedSideEffectImports === undefined) + compilerOptions.noUncheckedSideEffectImports = false; + // strict and types: don't inject when the tsconfig extends a base — the base may + // already set these, and an explicit value here would silently override the inherited one. + if (!tsconfig.extends) { + if (compilerOptions.strict === undefined) compilerOptions.strict = false; + // TS 6 stopped auto-discovering @types/* packages (types defaults to []). + // Seed the types every Bit env installs — @types/node universally and @types/jest + // (provides describe/it/expect globals). Don't seed 'mocha': the React env + // removes @types/mocha via the `-` convention (see react.env.ts), so seeding it + // would make tsc fail to resolve a type package that isn't installed. + if (compilerOptions.types === undefined) compilerOptions.types = ['node', 'jest']; + } + } const afterMutationWithoutTsconfig = { ...afterMutation.raw, tsconfig: '' }; return new TypescriptCompiler( diff --git a/tsconfig.json b/tsconfig.json index bca37334c636..26c1125bff5a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,9 @@ "strict": true, "moduleResolution": "node", "module": "commonjs", + "ignoreDeprecations": "6.0", + "noUncheckedSideEffectImports": false, + "types": ["node", "mocha", "chai", "jest"], "target": "es2015", "skipLibCheck": true, "noImplicitAny": false, diff --git a/workspace.jsonc b/workspace.jsonc index a4e4228cad4a..c4a39797ab62 100644 --- a/workspace.jsonc +++ b/workspace.jsonc @@ -397,6 +397,7 @@ "@types/lodash.flatten": "4.4.6", "@types/lodash.head": "4.0.6", "@types/mdx-js__react": "1.5.5", + "@types/jest": "29.5.14", "@types/memoizee": "0.4.5", "@types/mime": "2.0.3", "@types/mini-css-extract-plugin": "2.2.0", @@ -642,7 +643,7 @@ "tippy.js": "6.2.7", "ts-graphviz": "^2.1.6", "type-coverage": "2.15.1", - "typescript": "5.9.2", + "typescript": "6.0.3", "ua-parser-js": "0.7.40", "uid-number": "0.0.6", "uniqid": "5.3.0", @@ -834,7 +835,7 @@ "buffer": "6.0.3", "process": "0.11.10", "react-router-dom": "6.3.0", - "typescript": "5.9.2", + "typescript": "6.0.3", // @parcel/css, lightningcss, @swc/css are used by css-minimizer-webpack-plugin // see this issue https://github.com/webpack-contrib/css-minimizer-webpack-plugin/issues/244 "@parcel/css": "^1.8.3",