diff --git a/tsc/internal/checker/pseudotypenodebuilder.go b/tsc/internal/checker/pseudotypenodebuilder.go index 9daf4b686fc43..b70632f64ae40 100644 --- a/tsc/internal/checker/pseudotypenodebuilder.go +++ b/tsc/internal/checker/pseudotypenodebuilder.go @@ -184,7 +184,15 @@ func (b *NodeBuilderImpl) pseudoTypeToNode(t *pseudochecker.PseudoType) *ast.Nod if len(d.TypeParameters) > 0 { res := make([]*ast.Node, 0, len(d.TypeParameters)) for _, tp := range d.TypeParameters { - res = append(res, b.reuseNode(tp.AsNode())) + node := tp.AsNode() + reused := b.reuseNode(node) + if reused == nil { + // Reuse fails when the constraint references a name inaccessible from the emit target. + // A nil here would reach the printer, which dereferences it in NodeList.HasTrailingComma. + b.ctx.tracker.ReportInferenceFallback(node) + reused = b.typeParameterToDeclaration(b.ch.getDeclaredTypeOfTypeParameter(node.Symbol())) + } + res = append(res, reused) } typeParams = b.f.NewNodeList(res) } diff --git a/tsc/internal/execute/tsctests/tsc_test.go b/tsc/internal/execute/tsctests/tsc_test.go index 43e4949f3ba3c..3a28d8fe25d87 100644 --- a/tsc/internal/execute/tsctests/tsc_test.go +++ b/tsc/internal/execute/tsctests/tsc_test.go @@ -845,6 +845,75 @@ func TestTscDeclarationEmit(t *testing.T) { }, }, }, + { + // The declaration signature computed for b.ts inlines `setField` structurally. Its type + // parameters cannot be reused, because rewriting `typeof state` hits an inaccessible + // `unique symbol`. The pseudo type node builder used to store the resulting nils in the + // type parameter list, which crashed the printer (NodeList.HasTrailingComma). + // Two type parameters, so the fallback is exercised past the first list slot. + subScenario: "dts signature update with type parameters that cannot be reused", + files: FileMap{ + "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(` + { + "compilerOptions": { + "strict": true, + "incremental": true, + "skipLibCheck": true, + "skipDefaultLibCheck": true, + }, + }`), + "/home/src/workspaces/project/a.ts": stringtestutil.Dedent(` + declare const brand: unique symbol; + const state = { name: "", count: 0, [brand]: true }; + export const api = { + setField: (key: K, value: (typeof state)[K], tag?: Tag): void => { + state[key] = value; + void tag; + }, + };`), + "/home/src/workspaces/project/b.ts": stringtestutil.Dedent(` + import { api } from "./a"; + export const merged = { ...api };`), + }, + edits: []*tscEdit{ + newTscEdit("modify b.ts", func(sys *TestSys) { + sys.appendFile("/home/src/workspaces/project/b.ts", "\nexport const touched = 1;") + }), + }, + }, + { + // Same defect through the object-literal *method* branch: a shorthand method's type + // parameter list is rebuilt with reuseNode too, and a failed reuse used to leave a nil + // in the list the printer dereferences. + subScenario: "dts signature update with a method type parameter that cannot be reused", + files: FileMap{ + "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(` + { + "compilerOptions": { + "strict": true, + "incremental": true, + "skipLibCheck": true, + "skipDefaultLibCheck": true, + }, + }`), + "/home/src/workspaces/project/a.ts": stringtestutil.Dedent(` + declare const brand: unique symbol; + const state = { name: "", count: 0, [brand]: true }; + export const api = { + setField(key: K, value: (typeof state)[K]): void { + state[key] = value; + }, + };`), + "/home/src/workspaces/project/b.ts": stringtestutil.Dedent(` + import { api } from "./a"; + export const merged = { ...api };`), + }, + edits: []*tscEdit{ + newTscEdit("modify b.ts", func(sys *TestSys) { + sys.appendFile("/home/src/workspaces/project/b.ts", "\nexport const touched = 1;") + }), + }, + }, { subScenario: "when using Windows paths and uppercase letters", files: FileMap{ diff --git a/tsc/testdata/baselines/reference/tsc/declarationEmit/dts-signature-update-with-a-method-type-parameter-that-cannot-be-reused.js b/tsc/testdata/baselines/reference/tsc/declarationEmit/dts-signature-update-with-a-method-type-parameter-that-cannot-be-reused.js new file mode 100644 index 0000000000000..655595612b459 --- /dev/null +++ b/tsc/testdata/baselines/reference/tsc/declarationEmit/dts-signature-update-with-a-method-type-parameter-that-cannot-be-reused.js @@ -0,0 +1,226 @@ +currentDirectory::/home/src/workspaces/project +useCaseSensitiveFileNames::true +Input:: +//// [/home/src/workspaces/project/a.ts] *new* +declare const brand: unique symbol; +const state = { name: "", count: 0, [brand]: true }; +export const api = { + setField(key: K, value: (typeof state)[K]): void { + state[key] = value; + }, +}; +//// [/home/src/workspaces/project/b.ts] *new* +import { api } from "./a"; +export const merged = { ...api }; +//// [/home/src/workspaces/project/tsconfig.json] *new* +{ + "compilerOptions": { + "strict": true, + "incremental": true, + "skipLibCheck": true, + "skipDefaultLibCheck": true, + }, +} + +tsgo +ExitStatus:: Success +Output:: +//// [/home/src/tslibs/TS/Lib/lib.es2025.full.d.ts] *Lib* +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +interface SymbolConstructor { + (desc?: string | number): symbol; + for(name: string): symbol; + readonly toStringTag: symbol; +} +declare var Symbol: SymbolConstructor; +interface Symbol { + readonly [Symbol.toStringTag]: string; +} +declare const console: { log(msg: any): void; }; +//// [/home/src/workspaces/project/a.js] *new* +const state = { name: "", count: 0, [brand]: true }; +export const api = { + setField(key, value) { + state[key] = value; + }, +}; + +//// [/home/src/workspaces/project/b.js] *new* +import { api } from "./a"; +export const merged = { ...api }; + +//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *new* +{"version":"FakeTSVersion","root":[[2,3]],"fileNames":["lib.es2025.full.d.ts","./a.ts","./b.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},"c368b55602be64a94c816c58ca537602-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField(key: K, value: (typeof state)[K]): void {\n state[key] = value;\n },\n};","de62ab78d5ba64a5b325bfebf0f2e8d3-import { api } from \"./a\";\nexport const merged = { ...api };"],"fileIdsList":[[2]],"options":{"skipLibCheck":true,"strict":true,"skipDefaultLibCheck":true},"referencedMap":[[3,1]]} +//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *new* +{ + "version": "FakeTSVersion", + "root": [ + { + "files": [ + "./a.ts", + "./b.ts" + ], + "original": [ + 2, + 3 + ] + } + ], + "fileNames": [ + "lib.es2025.full.d.ts", + "./a.ts", + "./b.ts" + ], + "fileInfos": [ + { + "fileName": "lib.es2025.full.d.ts", + "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true, + "impliedNodeFormat": "CommonJS", + "original": { + "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + } + }, + { + "fileName": "./a.ts", + "version": "c368b55602be64a94c816c58ca537602-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField(key: K, value: (typeof state)[K]): void {\n state[key] = value;\n },\n};", + "signature": "c368b55602be64a94c816c58ca537602-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField(key: K, value: (typeof state)[K]): void {\n state[key] = value;\n },\n};", + "impliedNodeFormat": "CommonJS" + }, + { + "fileName": "./b.ts", + "version": "de62ab78d5ba64a5b325bfebf0f2e8d3-import { api } from \"./a\";\nexport const merged = { ...api };", + "signature": "de62ab78d5ba64a5b325bfebf0f2e8d3-import { api } from \"./a\";\nexport const merged = { ...api };", + "impliedNodeFormat": "CommonJS" + } + ], + "fileIdsList": [ + [ + "./a.ts" + ] + ], + "options": { + "skipLibCheck": true, + "strict": true, + "skipDefaultLibCheck": true + }, + "referencedMap": { + "./b.ts": [ + "./a.ts" + ] + }, + "size": 1373 +} + +tsconfig.json:: +SemanticDiagnostics:: +*refresh* /home/src/tslibs/TS/Lib/lib.es2025.full.d.ts +*refresh* /home/src/workspaces/project/a.ts +*refresh* /home/src/workspaces/project/b.ts +Signatures:: + + +Edit [0]:: modify b.ts +//// [/home/src/workspaces/project/b.ts] *modified* +import { api } from "./a"; +export const merged = { ...api }; +export const touched = 1; + +tsgo +ExitStatus:: Success +Output:: +//// [/home/src/workspaces/project/b.js] *modified* +import { api } from "./a"; +export const merged = { ...api }; +export const touched = 1; + +//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified* +{"version":"FakeTSVersion","root":[[2,3]],"fileNames":["lib.es2025.full.d.ts","./a.ts","./b.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},"c368b55602be64a94c816c58ca537602-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField(key: K, value: (typeof state)[K]): void {\n state[key] = value;\n },\n};",{"version":"6fa50051a3b923ced64e589b1e168966-import { api } from \"./a\";\nexport const merged = { ...api };\nexport const touched = 1;","signature":"a3ac76954f3eefab9ab3a4c186b22a76-export declare const merged: {\n setField(key: K, value: ({\n name: string;\n count: number;\n [brand]: boolean;\n })[K]): void;\n};\nexport declare const touched = 1;\n\n(40,6): error2527: The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary_2527\nmerged\nunique symbol\n\n(40,6): error4023: Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named_4023\nmerged\nbrand\n\"/home/src/workspaces/project/a\"\n","impliedNodeFormat":1}],"fileIdsList":[[2]],"options":{"skipLibCheck":true,"strict":true,"skipDefaultLibCheck":true},"referencedMap":[[3,1]]} +//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified* +{ + "version": "FakeTSVersion", + "root": [ + { + "files": [ + "./a.ts", + "./b.ts" + ], + "original": [ + 2, + 3 + ] + } + ], + "fileNames": [ + "lib.es2025.full.d.ts", + "./a.ts", + "./b.ts" + ], + "fileInfos": [ + { + "fileName": "lib.es2025.full.d.ts", + "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true, + "impliedNodeFormat": "CommonJS", + "original": { + "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + } + }, + { + "fileName": "./a.ts", + "version": "c368b55602be64a94c816c58ca537602-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField(key: K, value: (typeof state)[K]): void {\n state[key] = value;\n },\n};", + "signature": "c368b55602be64a94c816c58ca537602-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField(key: K, value: (typeof state)[K]): void {\n state[key] = value;\n },\n};", + "impliedNodeFormat": "CommonJS" + }, + { + "fileName": "./b.ts", + "version": "6fa50051a3b923ced64e589b1e168966-import { api } from \"./a\";\nexport const merged = { ...api };\nexport const touched = 1;", + "signature": "a3ac76954f3eefab9ab3a4c186b22a76-export declare const merged: {\n setField(key: K, value: ({\n name: string;\n count: number;\n [brand]: boolean;\n })[K]): void;\n};\nexport declare const touched = 1;\n\n(40,6): error2527: The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary_2527\nmerged\nunique symbol\n\n(40,6): error4023: Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named_4023\nmerged\nbrand\n\"/home/src/workspaces/project/a\"\n", + "impliedNodeFormat": "CommonJS", + "original": { + "version": "6fa50051a3b923ced64e589b1e168966-import { api } from \"./a\";\nexport const merged = { ...api };\nexport const touched = 1;", + "signature": "a3ac76954f3eefab9ab3a4c186b22a76-export declare const merged: {\n setField(key: K, value: ({\n name: string;\n count: number;\n [brand]: boolean;\n })[K]): void;\n};\nexport declare const touched = 1;\n\n(40,6): error2527: The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary_2527\nmerged\nunique symbol\n\n(40,6): error4023: Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named_4023\nmerged\nbrand\n\"/home/src/workspaces/project/a\"\n", + "impliedNodeFormat": 1 + } + } + ], + "fileIdsList": [ + [ + "./a.ts" + ] + ], + "options": { + "skipLibCheck": true, + "strict": true, + "skipDefaultLibCheck": true + }, + "referencedMap": { + "./b.ts": [ + "./a.ts" + ] + }, + "size": 2028 +} + +tsconfig.json:: +SemanticDiagnostics:: +*refresh* /home/src/workspaces/project/b.ts +Signatures:: +(computed .d.ts) /home/src/workspaces/project/b.ts diff --git a/tsc/testdata/baselines/reference/tsc/declarationEmit/dts-signature-update-with-type-parameters-that-cannot-be-reused.js b/tsc/testdata/baselines/reference/tsc/declarationEmit/dts-signature-update-with-type-parameters-that-cannot-be-reused.js new file mode 100644 index 0000000000000..5582ea6a03513 --- /dev/null +++ b/tsc/testdata/baselines/reference/tsc/declarationEmit/dts-signature-update-with-type-parameters-that-cannot-be-reused.js @@ -0,0 +1,228 @@ +currentDirectory::/home/src/workspaces/project +useCaseSensitiveFileNames::true +Input:: +//// [/home/src/workspaces/project/a.ts] *new* +declare const brand: unique symbol; +const state = { name: "", count: 0, [brand]: true }; +export const api = { + setField: (key: K, value: (typeof state)[K], tag?: Tag): void => { + state[key] = value; + void tag; + }, +}; +//// [/home/src/workspaces/project/b.ts] *new* +import { api } from "./a"; +export const merged = { ...api }; +//// [/home/src/workspaces/project/tsconfig.json] *new* +{ + "compilerOptions": { + "strict": true, + "incremental": true, + "skipLibCheck": true, + "skipDefaultLibCheck": true, + }, +} + +tsgo +ExitStatus:: Success +Output:: +//// [/home/src/tslibs/TS/Lib/lib.es2025.full.d.ts] *Lib* +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +interface SymbolConstructor { + (desc?: string | number): symbol; + for(name: string): symbol; + readonly toStringTag: symbol; +} +declare var Symbol: SymbolConstructor; +interface Symbol { + readonly [Symbol.toStringTag]: string; +} +declare const console: { log(msg: any): void; }; +//// [/home/src/workspaces/project/a.js] *new* +const state = { name: "", count: 0, [brand]: true }; +export const api = { + setField: (key, value, tag) => { + state[key] = value; + void tag; + }, +}; + +//// [/home/src/workspaces/project/b.js] *new* +import { api } from "./a"; +export const merged = { ...api }; + +//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *new* +{"version":"FakeTSVersion","root":[[2,3]],"fileNames":["lib.es2025.full.d.ts","./a.ts","./b.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},"639378dd59ee034bc0a35c6155f1f39d-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField: (key: K, value: (typeof state)[K], tag?: Tag): void => {\n state[key] = value;\n void tag;\n },\n};","de62ab78d5ba64a5b325bfebf0f2e8d3-import { api } from \"./a\";\nexport const merged = { ...api };"],"fileIdsList":[[2]],"options":{"skipLibCheck":true,"strict":true,"skipDefaultLibCheck":true},"referencedMap":[[3,1]]} +//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *new* +{ + "version": "FakeTSVersion", + "root": [ + { + "files": [ + "./a.ts", + "./b.ts" + ], + "original": [ + 2, + 3 + ] + } + ], + "fileNames": [ + "lib.es2025.full.d.ts", + "./a.ts", + "./b.ts" + ], + "fileInfos": [ + { + "fileName": "lib.es2025.full.d.ts", + "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true, + "impliedNodeFormat": "CommonJS", + "original": { + "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + } + }, + { + "fileName": "./a.ts", + "version": "639378dd59ee034bc0a35c6155f1f39d-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField: (key: K, value: (typeof state)[K], tag?: Tag): void => {\n state[key] = value;\n void tag;\n },\n};", + "signature": "639378dd59ee034bc0a35c6155f1f39d-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField: (key: K, value: (typeof state)[K], tag?: Tag): void => {\n state[key] = value;\n void tag;\n },\n};", + "impliedNodeFormat": "CommonJS" + }, + { + "fileName": "./b.ts", + "version": "de62ab78d5ba64a5b325bfebf0f2e8d3-import { api } from \"./a\";\nexport const merged = { ...api };", + "signature": "de62ab78d5ba64a5b325bfebf0f2e8d3-import { api } from \"./a\";\nexport const merged = { ...api };", + "impliedNodeFormat": "CommonJS" + } + ], + "fileIdsList": [ + [ + "./a.ts" + ] + ], + "options": { + "skipLibCheck": true, + "strict": true, + "skipDefaultLibCheck": true + }, + "referencedMap": { + "./b.ts": [ + "./a.ts" + ] + }, + "size": 1428 +} + +tsconfig.json:: +SemanticDiagnostics:: +*refresh* /home/src/tslibs/TS/Lib/lib.es2025.full.d.ts +*refresh* /home/src/workspaces/project/a.ts +*refresh* /home/src/workspaces/project/b.ts +Signatures:: + + +Edit [0]:: modify b.ts +//// [/home/src/workspaces/project/b.ts] *modified* +import { api } from "./a"; +export const merged = { ...api }; +export const touched = 1; + +tsgo +ExitStatus:: Success +Output:: +//// [/home/src/workspaces/project/b.js] *modified* +import { api } from "./a"; +export const merged = { ...api }; +export const touched = 1; + +//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified* +{"version":"FakeTSVersion","root":[[2,3]],"fileNames":["lib.es2025.full.d.ts","./a.ts","./b.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},"639378dd59ee034bc0a35c6155f1f39d-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField: (key: K, value: (typeof state)[K], tag?: Tag): void => {\n state[key] = value;\n void tag;\n },\n};",{"version":"6fa50051a3b923ced64e589b1e168966-import { api } from \"./a\";\nexport const merged = { ...api };\nexport const touched = 1;","signature":"dc61af78c711b5b05731ae4cbc47c2ca-export declare const merged: {\n setField: (key: K, value: ({\n name: string;\n count: number;\n [brand]: boolean;\n })[K], tag?: Tag) => void;\n};\nexport declare const touched = 1;\n\n(40,6): error2527: The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary_2527\nmerged\nunique symbol\n\n(40,6): error4023: Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named_4023\nmerged\nbrand\n\"/home/src/workspaces/project/a\"\n","impliedNodeFormat":1}],"fileIdsList":[[2]],"options":{"skipLibCheck":true,"strict":true,"skipDefaultLibCheck":true},"referencedMap":[[3,1]]} +//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified* +{ + "version": "FakeTSVersion", + "root": [ + { + "files": [ + "./a.ts", + "./b.ts" + ], + "original": [ + 2, + 3 + ] + } + ], + "fileNames": [ + "lib.es2025.full.d.ts", + "./a.ts", + "./b.ts" + ], + "fileInfos": [ + { + "fileName": "lib.es2025.full.d.ts", + "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true, + "impliedNodeFormat": "CommonJS", + "original": { + "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + } + }, + { + "fileName": "./a.ts", + "version": "639378dd59ee034bc0a35c6155f1f39d-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField: (key: K, value: (typeof state)[K], tag?: Tag): void => {\n state[key] = value;\n void tag;\n },\n};", + "signature": "639378dd59ee034bc0a35c6155f1f39d-declare const brand: unique symbol;\nconst state = { name: \"\", count: 0, [brand]: true };\nexport const api = {\n setField: (key: K, value: (typeof state)[K], tag?: Tag): void => {\n state[key] = value;\n void tag;\n },\n};", + "impliedNodeFormat": "CommonJS" + }, + { + "fileName": "./b.ts", + "version": "6fa50051a3b923ced64e589b1e168966-import { api } from \"./a\";\nexport const merged = { ...api };\nexport const touched = 1;", + "signature": "dc61af78c711b5b05731ae4cbc47c2ca-export declare const merged: {\n setField: (key: K, value: ({\n name: string;\n count: number;\n [brand]: boolean;\n })[K], tag?: Tag) => void;\n};\nexport declare const touched = 1;\n\n(40,6): error2527: The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary_2527\nmerged\nunique symbol\n\n(40,6): error4023: Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named_4023\nmerged\nbrand\n\"/home/src/workspaces/project/a\"\n", + "impliedNodeFormat": "CommonJS", + "original": { + "version": "6fa50051a3b923ced64e589b1e168966-import { api } from \"./a\";\nexport const merged = { ...api };\nexport const touched = 1;", + "signature": "dc61af78c711b5b05731ae4cbc47c2ca-export declare const merged: {\n setField: (key: K, value: ({\n name: string;\n count: number;\n [brand]: boolean;\n })[K], tag?: Tag) => void;\n};\nexport declare const touched = 1;\n\n(40,6): error2527: The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary_2527\nmerged\nunique symbol\n\n(40,6): error4023: Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named_4023\nmerged\nbrand\n\"/home/src/workspaces/project/a\"\n", + "impliedNodeFormat": 1 + } + } + ], + "fileIdsList": [ + [ + "./a.ts" + ] + ], + "options": { + "skipLibCheck": true, + "strict": true, + "skipDefaultLibCheck": true + }, + "referencedMap": { + "./b.ts": [ + "./a.ts" + ] + }, + "size": 2118 +} + +tsconfig.json:: +SemanticDiagnostics:: +*refresh* /home/src/workspaces/project/b.ts +Signatures:: +(computed .d.ts) /home/src/workspaces/project/b.ts