From ded8a85be3af0f27836371dbd525be9f21768a72 Mon Sep 17 00:00:00 2001 From: Colin McDonnell <3084745+colinhacks@users.noreply.github.com> Date: Fri, 9 Oct 2026 17:06:43 -0700 Subject: [PATCH] Copy JSDoc from mapped type properties in declaration emit --- tsc/internal/checker/nodebuilderimpl.go | 2 +- .../declarationEmitMappedTypePropertyJSDoc.js | 40 +++++++++++++ ...arationEmitMappedTypePropertyJSDoc.symbols | 56 +++++++++++++++++++ ...clarationEmitMappedTypePropertyJSDoc.types | 46 +++++++++++++++ .../declarationEmitMappedTypePropertyJSDoc.ts | 13 +++++ 5 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.js create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.types create mode 100644 tsc/testdata/tests/cases/compiler/declarationEmitMappedTypePropertyJSDoc.ts diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index cd4643ac6f273..4ab5f999dd1d3 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -2713,7 +2713,7 @@ func (b *NodeBuilderImpl) addPropertyToElementList(propertySymbol *ast.Symbol, t } propertySignature := b.f.NewPropertySignatureDeclaration(modifiers, propertyName, optionalToken, propertyTypeNode, nil) - b.setCommentRange(propertySignature, propertySymbol.ValueDeclaration()) + b.setCommentRange(propertySignature, core.Coalesce(propertySymbol.ValueDeclaration(), core.FirstOrNil(propertySymbol.Declarations()))) typeElements = append(typeElements, propertySignature) return typeElements diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.js b/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.js new file mode 100644 index 0000000000000..e022681ad2d16 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.js @@ -0,0 +1,40 @@ +//// [tests/cases/compiler/declarationEmitMappedTypePropertyJSDoc.ts] //// + +//// [declarationEmitMappedTypePropertyJSDoc.ts] +type Writeable = { -readonly [P in keyof T]: T[P] } & {}; +declare function make(shape: T): { shape: Writeable }; +export const a = make({ + /** doc for x */ + x: 1, +}); +declare function pick(t: T, k: K): { [P in K]: T[P] }; +export const b = pick({ + /** doc for v */ + v: 1, + w: 2, +}, "v"); + + +//// [declarationEmitMappedTypePropertyJSDoc.js] +export const a = make({ + /** doc for x */ + x: 1, +}); +export const b = pick({ + /** doc for v */ + v: 1, + w: 2, +}, "v"); + + +//// [declarationEmitMappedTypePropertyJSDoc.d.ts] +export declare const a: { + shape: { + /** doc for x */ + x: number; + }; +}; +export declare const b: { + /** doc for v */ + v: number; +}; diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.symbols b/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.symbols new file mode 100644 index 0000000000000..5a5b26cf7077c --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.symbols @@ -0,0 +1,56 @@ +//// [tests/cases/compiler/declarationEmitMappedTypePropertyJSDoc.ts] //// + +=== declarationEmitMappedTypePropertyJSDoc.ts === +type Writeable = { -readonly [P in keyof T]: T[P] } & {}; +>Writeable : Symbol(Writeable, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 0)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 15)) +>P : Symbol(P, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 33)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 15)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 15)) +>P : Symbol(P, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 33)) + +declare function make(shape: T): { shape: Writeable }; +>make : Symbol(make, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 60)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 1, 22)) +>shape : Symbol(shape, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 1, 25)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 1, 22)) +>shape : Symbol(shape, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 1, 37)) +>Writeable : Symbol(Writeable, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 0)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 1, 22)) + +export const a = make({ +>a : Symbol(a, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 2, 12)) +>make : Symbol(make, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 0, 60)) + + /** doc for x */ + x: 1, +>x : Symbol(x, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 2, 23)) + +}); +declare function pick(t: T, k: K): { [P in K]: T[P] }; +>pick : Symbol(pick, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 5, 3)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 22)) +>K : Symbol(K, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 24)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 22)) +>t : Symbol(t, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 44)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 22)) +>k : Symbol(k, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 49)) +>K : Symbol(K, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 24)) +>P : Symbol(P, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 60)) +>K : Symbol(K, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 24)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 22)) +>P : Symbol(P, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 6, 60)) + +export const b = pick({ +>b : Symbol(b, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 7, 12)) +>pick : Symbol(pick, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 5, 3)) + + /** doc for v */ + v: 1, +>v : Symbol(v, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 7, 23)) + + w: 2, +>w : Symbol(w, Decl(declarationEmitMappedTypePropertyJSDoc.ts, 9, 7)) + +}, "v"); + diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.types b/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.types new file mode 100644 index 0000000000000..5fb3664cd69c8 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitMappedTypePropertyJSDoc.types @@ -0,0 +1,46 @@ +//// [tests/cases/compiler/declarationEmitMappedTypePropertyJSDoc.ts] //// + +=== declarationEmitMappedTypePropertyJSDoc.ts === +type Writeable = { -readonly [P in keyof T]: T[P] } & {}; +>Writeable : { -readonly [P in keyof T]: T[P]; } + +declare function make(shape: T): { shape: Writeable }; +>make : (shape: T) => { shape: Writeable; } +>shape : T +>shape : { -readonly [P in keyof T]: T[P]; } + +export const a = make({ +>a : { shape: { x: number; }; } +>make({ /** doc for x */ x: 1,}) : { shape: { x: number; }; } +>make : (shape: T) => { shape: Writeable; } +>{ /** doc for x */ x: 1,} : { x: number; } + + /** doc for x */ + x: 1, +>x : number +>1 : 1 + +}); +declare function pick(t: T, k: K): { [P in K]: T[P] }; +>pick : (t: T, k: K) => { [P in K]: T[P]; } +>t : T +>k : K + +export const b = pick({ +>b : { v: number; } +>pick({ /** doc for v */ v: 1, w: 2,}, "v") : { v: number; } +>pick : (t: T, k: K) => { [P in K]: T[P]; } +>{ /** doc for v */ v: 1, w: 2,} : { v: number; w: number; } + + /** doc for v */ + v: 1, +>v : number +>1 : 1 + + w: 2, +>w : number +>2 : 2 + +}, "v"); +>"v" : "v" + diff --git a/tsc/testdata/tests/cases/compiler/declarationEmitMappedTypePropertyJSDoc.ts b/tsc/testdata/tests/cases/compiler/declarationEmitMappedTypePropertyJSDoc.ts new file mode 100644 index 0000000000000..2d235b97125cf --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/declarationEmitMappedTypePropertyJSDoc.ts @@ -0,0 +1,13 @@ +// @declaration: true +type Writeable = { -readonly [P in keyof T]: T[P] } & {}; +declare function make(shape: T): { shape: Writeable }; +export const a = make({ + /** doc for x */ + x: 1, +}); +declare function pick(t: T, k: K): { [P in K]: T[P] }; +export const b = pick({ + /** doc for v */ + v: 1, + w: 2, +}, "v");