diff --git a/tsc/internal/parser/jsdoc.go b/tsc/internal/parser/jsdoc.go index 6d239d2f228fc..02ed4887d4585 100644 --- a/tsc/internal/parser/jsdoc.go +++ b/tsc/internal/parser/jsdoc.go @@ -1197,6 +1197,7 @@ func (p *Parser) parseChildParameterOrPropertyTag(target propertyLikeParse, inde child := p.tryParseChildTag(target, indent) if child != nil && name != nil && (child.Kind == ast.KindJSDocParameterTag || child.Kind == ast.KindJSDocPropertyTag) && + !ast.NodeIsMissing(child.Name()) && (ast.IsIdentifier(child.Name()) || !textsEqual(name, child.Name().AsQualifiedName().Left)) { return nil } diff --git a/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.errors.txt b/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.errors.txt new file mode 100644 index 0000000000000..38f1717287636 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.errors.txt @@ -0,0 +1,33 @@ +/a.js(5,23): error TS1005: '}' expected. +/a.js(12,23): error TS1005: '}' expected. + + +==== /a.js (2 errors) ==== + /** + * @typedef Sig + * @property {object} Args + * @property {string} Args.name + * @property {function(string)=} Args.onSave + ~ +!!! error TS1005: '}' expected. + * @property {((v: string) => void)=} Args.onCancel + */ + + /** + * @typedef Flat + * @property {string} name + * @property {function(string)=} onSave + ~ +!!! error TS1005: '}' expected. + * @property {((v: string) => void)=} onCancel + */ + + export {}; + +==== /b.ts (0 errors) ==== + import type { Sig, Flat } from "./a.js"; + + export const nested: Array = ["name", "onCancel"]; + export const flat: Array = ["name", "onCancel"]; + export const onCancel: Sig["Args"]["onCancel"] = (v: string) => {}; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.symbols b/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.symbols new file mode 100644 index 0000000000000..a32c2b0e1d739 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.symbols @@ -0,0 +1,41 @@ +//// [tests/cases/compiler/jsdocNestedPropertyTagInvalidType.ts] //// + +=== /a.js === + +/** + * @typedef Sig + * @property {object} Args + * @property {string} Args.name + * @property {function(string)=} Args.onSave + * @property {((v: string) => void)=} Args.onCancel + */ + +/** + * @typedef Flat + * @property {string} name + * @property {function(string)=} onSave + * @property {((v: string) => void)=} onCancel + */ + +export {}; + +=== /b.ts === +import type { Sig, Flat } from "./a.js"; +>Sig : Symbol(Sig, Decl(b.ts, 0, 13)) +>Flat : Symbol(Flat, Decl(b.ts, 0, 18)) + +export const nested: Array = ["name", "onCancel"]; +>nested : Symbol(nested, Decl(b.ts, 2, 12)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 4 more) +>Sig : Symbol(Sig, Decl(b.ts, 0, 13)) + +export const flat: Array = ["name", "onCancel"]; +>flat : Symbol(flat, Decl(b.ts, 3, 12)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 4 more) +>Flat : Symbol(Flat, Decl(b.ts, 0, 18)) + +export const onCancel: Sig["Args"]["onCancel"] = (v: string) => {}; +>onCancel : Symbol(onCancel, Decl(b.ts, 4, 12)) +>Sig : Symbol(Sig, Decl(b.ts, 0, 13)) +>v : Symbol(v, Decl(b.ts, 4, 50)) + diff --git a/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.types b/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.types new file mode 100644 index 0000000000000..d6dab7e94792c --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyTagInvalidType.types @@ -0,0 +1,43 @@ +//// [tests/cases/compiler/jsdocNestedPropertyTagInvalidType.ts] //// + +=== /a.js === + +/** + * @typedef Sig + * @property {object} Args + * @property {string} Args.name + * @property {function(string)=} Args.onSave + * @property {((v: string) => void)=} Args.onCancel + */ + +/** + * @typedef Flat + * @property {string} name + * @property {function(string)=} onSave + * @property {((v: string) => void)=} onCancel + */ + +export {}; + +=== /b.ts === +import type { Sig, Flat } from "./a.js"; +>Sig : Sig +>Flat : Flat + +export const nested: Array = ["name", "onCancel"]; +>nested : ("" | "name" | "onCancel")[] +>["name", "onCancel"] : ("name" | "onCancel")[] +>"name" : "name" +>"onCancel" : "onCancel" + +export const flat: Array = ["name", "onCancel"]; +>flat : (keyof Flat)[] +>["name", "onCancel"] : ("name" | "onCancel")[] +>"name" : "name" +>"onCancel" : "onCancel" + +export const onCancel: Sig["Args"]["onCancel"] = (v: string) => {}; +>onCancel : ((v: string) => void) | undefined +>(v: string) => {} : (v: string) => void +>v : string + diff --git a/tsc/testdata/tests/cases/compiler/jsdocNestedPropertyTagInvalidType.ts b/tsc/testdata/tests/cases/compiler/jsdocNestedPropertyTagInvalidType.ts new file mode 100644 index 0000000000000..b36652678755b --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/jsdocNestedPropertyTagInvalidType.ts @@ -0,0 +1,29 @@ +// @strict: true +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @Filename: /a.js +/** + * @typedef Sig + * @property {object} Args + * @property {string} Args.name + * @property {function(string)=} Args.onSave + * @property {((v: string) => void)=} Args.onCancel + */ + +/** + * @typedef Flat + * @property {string} name + * @property {function(string)=} onSave + * @property {((v: string) => void)=} onCancel + */ + +export {}; + +// @Filename: /b.ts +import type { Sig, Flat } from "./a.js"; + +export const nested: Array = ["name", "onCancel"]; +export const flat: Array = ["name", "onCancel"]; +export const onCancel: Sig["Args"]["onCancel"] = (v: string) => {};