From f58f5e9494d6dbeb07e87efb673e6eab37c33423 Mon Sep 17 00:00:00 2001 From: 64 <172265251+64qq@users.noreply.github.com> Date: Thu, 31 Jul 2025 01:22:42 +0900 Subject: [PATCH 1/4] Consolidate internal TypeScript API typings --- packages/ata/src/index.ts | 4 +- packages/ata/tsconfig.json | 1 + .../playground/src/createConfigDropdown.ts | 18 +-- packages/playground/tsconfig.json | 4 +- packages/sandbox/src/compilerOptions.ts | 1 - packages/sandbox/src/twoslashSupport.ts | 7 +- packages/sandbox/tsconfig.json | 2 +- packages/ts-internals/index.d.ts | 127 ++++++++++++++++++ packages/ts-internals/package.json | 12 ++ packages/ts-internals/tsconfig.json | 10 ++ packages/ts-twoslasher/src/index.ts | 11 -- packages/ts-twoslasher/tsconfig.json | 2 +- .../scripts/cli/generateJSON.ts | 14 +- .../scripts/schema/generateJSON.ts | 6 +- .../scripts/tsconfig/generateJSON.ts | 10 +- .../scripts/tsconfigRules.ts | 39 +----- packages/tsconfig-reference/scripts/types.ts | 81 ----------- packages/tsconfig-reference/tsconfig.json | 1 + pnpm-lock.yaml | 6 + 19 files changed, 184 insertions(+), 172 deletions(-) create mode 100644 packages/ts-internals/index.d.ts create mode 100644 packages/ts-internals/package.json create mode 100644 packages/ts-internals/tsconfig.json delete mode 100644 packages/tsconfig-reference/scripts/types.ts diff --git a/packages/ata/src/index.ts b/packages/ata/src/index.ts index a9755734646c..35ca0ee6b671 100644 --- a/packages/ata/src/index.ts +++ b/packages/ata/src/index.ts @@ -162,8 +162,8 @@ export const getReferencesForModule = (ts: typeof import("typescript"), code: st const meta = ts.preProcessFile(code) // Ensure we don't try download TypeScript lib references - // @ts-ignore - private but likely to never change - const libMap: Map = ts.libMap || new Map() + // private but likely to never change + const libMap = ts.libMap || new Map() // TODO: strip /// ? diff --git a/packages/ata/tsconfig.json b/packages/ata/tsconfig.json index e228c47e9e33..03adbb9e4984 100644 --- a/packages/ata/tsconfig.json +++ b/packages/ata/tsconfig.json @@ -1,4 +1,5 @@ { + "include": ["../ts-internals"], "compilerOptions": { "module": "ESNext", "moduleResolution": "node", diff --git a/packages/playground/src/createConfigDropdown.ts b/packages/playground/src/createConfigDropdown.ts index 030edff787e2..4b915735abb4 100644 --- a/packages/playground/src/createConfigDropdown.ts +++ b/packages/playground/src/createConfigDropdown.ts @@ -1,3 +1,5 @@ +import { CommandLineOption, CommandLineOptionOfBooleanType } from "typescript" + type Sandbox = import("@typescript/sandbox").Sandbox type Monaco = typeof import("monaco-editor") @@ -12,14 +14,6 @@ type OptionsSummary = { // This is where all the localized descriptions come from declare const optionsSummary: OptionsSummary[] -type CompilerOptStub = { - name: string - type: string - isCommandLineOnly: boolean - category: any - description: any -} - const notCompilerOptions = ["Project_Files_0", "Watch_Options_999", "Command_line_Options_6171"] const notRelevantToPlayground = [ "listFiles", @@ -56,15 +50,15 @@ export const createConfigDropdown = (sandbox: Sandbox, monaco: Monaco) => { container.id = "boolean-options-container" configContainer.appendChild(container) - // @ts-ignore - const allOptions: CompilerOptStub[] = sandbox.ts.optionDeclarations + const allOptions = sandbox.ts.optionDeclarations const boolOptions = allOptions.filter( - k => + (k): k is CommandLineOptionOfBooleanType & Required> => !notRelevantToPlayground.includes(k.name) && k.type === "boolean" && !k.isCommandLineOnly && - k.category && + !!k.category && + !!k.description && !notCompilerOptions.includes(k.category.key) ) diff --git a/packages/playground/tsconfig.json b/packages/playground/tsconfig.json index 885a5495a406..a3d961f9360e 100644 --- a/packages/playground/tsconfig.json +++ b/packages/playground/tsconfig.json @@ -1,5 +1,5 @@ { - "include": ["src"], + "include": ["src", "../ts-internals"], "compilerOptions": { "outDir": "../typescriptlang-org/static/js/playground", "jsx": "react", @@ -13,6 +13,6 @@ "strict": true, "moduleResolution": "node", "esModuleInterop": true, - "skipLibCheck": true, + "skipLibCheck": true } } diff --git a/packages/sandbox/src/compilerOptions.ts b/packages/sandbox/src/compilerOptions.ts index 7d319c0009d1..22474f4dbe67 100644 --- a/packages/sandbox/src/compilerOptions.ts +++ b/packages/sandbox/src/compilerOptions.ts @@ -94,7 +94,6 @@ export const getCompilerOptionsFromParams = ( if (toSet !== undefined) returnedOptions[key] = toSet } else { // If that doesn't work, double check that the flag exists and allow it through - // @ts-ignore const flagExists = ts.optionDeclarations.find(opt => opt.name === key) if (flagExists) { let realValue: number | boolean = true diff --git a/packages/sandbox/src/twoslashSupport.ts b/packages/sandbox/src/twoslashSupport.ts index 0a65beec4277..9068f7d2f490 100644 --- a/packages/sandbox/src/twoslashSupport.ts +++ b/packages/sandbox/src/twoslashSupport.ts @@ -5,6 +5,7 @@ const valuedConfigRegexp = /^\/\/\s?@(\w+):\s?(.+)$/ type TS = typeof import("typescript") type CompilerOptions = import("typescript").CompilerOptions +type CommandLineOption = import("typescript").CommandLineOption /** * This is a port of the twoslash bit which grabs compiler options @@ -12,12 +13,11 @@ type CompilerOptions = import("typescript").CompilerOptions */ export const extractTwoSlashCompilerOptions = (ts: TS) => { - let optMap = new Map() + const optMap = new Map() if (!("optionDeclarations" in ts)) { console.error("Could not get compiler options from ts.optionDeclarations - skipping twoslash support.") } else { - // @ts-ignore - optionDeclarations is not public API for (const opt of ts.optionDeclarations) { optMap.set(opt.name.toLowerCase(), opt) } @@ -45,7 +45,7 @@ export const extractTwoSlashCompilerOptions = (ts: TS) => { } } -function setOption(name: string, value: string, opts: CompilerOptions, optMap: Map) { +function setOption(name: string, value: string, opts: CompilerOptions, optMap: Map) { const opt = optMap.get(name.toLowerCase()) if (!opt) return @@ -161,7 +161,6 @@ export const twoslashCompletions = (ts: TS, monaco: typeof import("monaco-editor "noErrorValidation", "filename", ] - // @ts-ignore - ts.optionDeclarations is private const optsNames = ts.optionDeclarations.map(o => o.name) knowns.concat(optsNames).forEach(name => { if (name.startsWith(word.slice(1))) { diff --git a/packages/sandbox/tsconfig.json b/packages/sandbox/tsconfig.json index 2612cde3e8a0..a8b6ebefa484 100644 --- a/packages/sandbox/tsconfig.json +++ b/packages/sandbox/tsconfig.json @@ -1,5 +1,5 @@ { - "include": ["src", "src/vendor/lzstring.min.js"], + "include": ["src", "src/vendor/lzstring.min.js", "../ts-internals"], "compilerOptions": { "outDir": "../typescriptlang-org/static/js/sandbox", diff --git a/packages/ts-internals/index.d.ts b/packages/ts-internals/index.d.ts new file mode 100644 index 000000000000..0edc6f4b7737 --- /dev/null +++ b/packages/ts-internals/index.d.ts @@ -0,0 +1,127 @@ +import "typescript" + +// These are all copy-pasted from https://github.com/microsoft/TypeScript/tree/be8678315541e814da14316848a9468e8f90ab11 +declare module "typescript" { + /** @internal */ + const optionDeclarations: CommandLineOption[] + /** @internal */ + const optionsForWatch: CommandLineOption[] + /** @internal */ + export const commonOptionsWithBuild: CommandLineOption[] + /** @internal */ + export const buildOpts: CommandLineOption[] + /** @internal */ + const typeAcquisitionDeclarations: CommandLineOption[] + /** @internal */ + const defaultInitCompilerOptions: CompilerOptions + /** + * A map of lib names to lib files. This map is used both for parsing the "lib" command line + * option as well as for resolving lib reference directives. + * + * @internal + */ + export const libMap: Map + + /** @internal */ + export interface OptionsNameMap { + optionsNameMap: Map + shortOptionNames: Map + } + + // prettier-ignore + /** @internal */ + export interface CommandLineOptionBase { + name: string; + type: "string" | "number" | "boolean" | "object" | "list" | "listOrElement" | Map; // a value of a primitive type, or an object literal mapping named values to actual values + isFilePath?: boolean; // True if option value is a path or fileName + shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help' + description?: DiagnosticMessage; // The message describing what the command line switch does. + defaultValueDescription?: string | number | boolean | DiagnosticMessage | undefined; // The message describing what the dafault value is. string type is prepared for fixed chosen like "false" which do not need I18n. + paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter + isTSConfigOnly?: boolean; // True if option can only be specified via tsconfig.json file + isCommandLineOnly?: boolean; + showInSimplifiedHelpView?: boolean; + category?: DiagnosticMessage; + strictFlag?: true; // true if the option is one of the flag under strict + allowJsFlag?: true; + affectsSourceFile?: true; // true if we should recreate SourceFiles after this option changes + affectsModuleResolution?: true; // currently same effect as `affectsSourceFile` + affectsBindDiagnostics?: true; // true if this affects binding (currently same effect as `affectsSourceFile`) + affectsSemanticDiagnostics?: true; // true if option affects semantic diagnostics + affectsEmit?: true; // true if the options affects emit + affectsProgramStructure?: true; // true if program should be reconstructed from root files if option changes and does not affect module resolution as affectsModuleResolution indirectly means program needs to reconstructed + affectsDeclarationPath?: true; // true if the options affects declaration file path computed + affectsBuildInfo?: true; // true if this options should be emitted in buildInfo + transpileOptionValue?: boolean | undefined; // If set this means that the option should be set to this value when transpiling + extraValidation?: (value: CompilerOptionsValue) => [DiagnosticMessage, ...string[]] | undefined; // Additional validation to be performed for the value to be valid + disallowNullOrUndefined?: true; // If set option does not allow setting null + allowConfigDirTemplateSubstitution?: true; // If set option allows substitution of `${configDir}` in the value +} + + /** @internal */ + export interface CommandLineOptionOfStringType extends CommandLineOptionBase { + type: "string" + defaultValueDescription?: string | undefined | DiagnosticMessage + } + + /** @internal */ + export interface CommandLineOptionOfNumberType extends CommandLineOptionBase { + type: "number" + defaultValueDescription: number | undefined | DiagnosticMessage + } + + /** @internal */ + export interface CommandLineOptionOfBooleanType extends CommandLineOptionBase { + type: "boolean" + defaultValueDescription: boolean | undefined | DiagnosticMessage + } + + /** @internal */ + export interface CommandLineOptionOfCustomType extends CommandLineOptionBase { + type: Map // an object literal mapping named values to actual values + defaultValueDescription: number | string | undefined | DiagnosticMessage + deprecatedKeys?: Set + } + + /** @internal */ + export interface AlternateModeDiagnostics { + diagnostic: DiagnosticMessage + getOptionsNameMap: () => OptionsNameMap + } + + /** @internal */ + export interface DidYouMeanOptionsDiagnostics { + alternateMode?: AlternateModeDiagnostics + optionDeclarations: CommandLineOption[] + unknownOptionDiagnostic: DiagnosticMessage + unknownDidYouMeanDiagnostic: DiagnosticMessage + } + + /** @internal */ + export interface TsConfigOnlyOption extends CommandLineOptionBase { + type: "object" + elementOptions?: Map + extraKeyDiagnostics?: DidYouMeanOptionsDiagnostics + } + + /** @internal */ + export interface CommandLineOptionOfListType extends CommandLineOptionBase { + type: "list" | "listOrElement" + element: + | CommandLineOptionOfCustomType + | CommandLineOptionOfStringType + | CommandLineOptionOfNumberType + | CommandLineOptionOfBooleanType + | TsConfigOnlyOption + listPreserveFalsyValues?: boolean + } + + /** @internal */ + export type CommandLineOption = + | CommandLineOptionOfCustomType + | CommandLineOptionOfStringType + | CommandLineOptionOfNumberType + | CommandLineOptionOfBooleanType + | TsConfigOnlyOption + | CommandLineOptionOfListType +} diff --git a/packages/ts-internals/package.json b/packages/ts-internals/package.json new file mode 100644 index 000000000000..68fd790a6e57 --- /dev/null +++ b/packages/ts-internals/package.json @@ -0,0 +1,12 @@ +{ + "name": "ts-internals", + "private": true, + "license": "MIT", + "version": "1.0.0", + "scripts": { + "build": "tsc --build ." + }, + "devDependencies": { + "typescript": "*" + } +} diff --git a/packages/ts-internals/tsconfig.json b/packages/ts-internals/tsconfig.json new file mode 100644 index 000000000000..37a4aee8ea57 --- /dev/null +++ b/packages/ts-internals/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES5", + "strict": true, + "skipLibCheck": false, + "noEmit": true + } +} diff --git a/packages/ts-twoslasher/src/index.ts b/packages/ts-twoslasher/src/index.ts index 0864bf3de185..8ad554786c0a 100755 --- a/packages/ts-twoslasher/src/index.ts +++ b/packages/ts-twoslasher/src/index.ts @@ -17,17 +17,6 @@ import { createSystem, createVirtualTypeScriptEnvironment, createFSBackedSystem const log = shouldDebug ? console.log : (_message?: any, ..._optionalParams: any[]) => "" -// Hacking in some internal stuff -declare module "typescript" { - type Option = { - name: string - type: "list" | "boolean" | "number" | "string" | Map - element?: Option - } - - const optionDeclarations: Array