From d5af89c552edca1bfeea903bf402b9898a514b1f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 26 Apr 2021 09:19:24 -0700 Subject: [PATCH] Contextual typing checks property assignments for type annotation (#43598) Property assignments can have a type annotation in JS. This PR adds a check for it in contextual typing. Fixes #43379 --- src/compiler/checker.ts | 4 +++ .../typeTagOnPropertyAssignment.symbols | 25 ++++++++++++++++ .../typeTagOnPropertyAssignment.types | 29 +++++++++++++++++++ .../jsdoc/typeTagOnPropertyAssignment.ts | 13 +++++++++ 4 files changed, 71 insertions(+) create mode 100644 tests/baselines/reference/typeTagOnPropertyAssignment.symbols create mode 100644 tests/baselines/reference/typeTagOnPropertyAssignment.types create mode 100644 tests/cases/conformance/jsdoc/typeTagOnPropertyAssignment.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 682a1e7435f..f4ee7960f10 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25218,6 +25218,10 @@ namespace ts { function getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike, contextFlags?: ContextFlags) { const objectLiteral = element.parent; + const propertyAssignmentType = isPropertyAssignment(element) && getContextualTypeForVariableLikeDeclaration(element); + if (propertyAssignmentType) { + return propertyAssignmentType; + } const type = getApparentTypeOfContextualType(objectLiteral, contextFlags); if (type) { if (hasBindableName(element)) { diff --git a/tests/baselines/reference/typeTagOnPropertyAssignment.symbols b/tests/baselines/reference/typeTagOnPropertyAssignment.symbols new file mode 100644 index 00000000000..d48e0b16fa6 --- /dev/null +++ b/tests/baselines/reference/typeTagOnPropertyAssignment.symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/jsdoc/typeTagOnPropertyAssignment.js === +const o = { +>o : Symbol(o, Decl(typeTagOnPropertyAssignment.js, 0, 5)) + + /** + * @type {"a"} + */ + a: "a", +>a : Symbol(a, Decl(typeTagOnPropertyAssignment.js, 0, 11)) + + /** @type {() => 'b'} */ + n: () => 'b' +>n : Symbol(n, Decl(typeTagOnPropertyAssignment.js, 4, 11)) + +}; +o.a +>o.a : Symbol(a, Decl(typeTagOnPropertyAssignment.js, 0, 11)) +>o : Symbol(o, Decl(typeTagOnPropertyAssignment.js, 0, 5)) +>a : Symbol(a, Decl(typeTagOnPropertyAssignment.js, 0, 11)) + +o.n +>o.n : Symbol(n, Decl(typeTagOnPropertyAssignment.js, 4, 11)) +>o : Symbol(o, Decl(typeTagOnPropertyAssignment.js, 0, 5)) +>n : Symbol(n, Decl(typeTagOnPropertyAssignment.js, 4, 11)) + diff --git a/tests/baselines/reference/typeTagOnPropertyAssignment.types b/tests/baselines/reference/typeTagOnPropertyAssignment.types new file mode 100644 index 00000000000..84ce1e1742b --- /dev/null +++ b/tests/baselines/reference/typeTagOnPropertyAssignment.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/jsdoc/typeTagOnPropertyAssignment.js === +const o = { +>o : { a: "a"; n: () => 'b'; } +>{ /** * @type {"a"} */ a: "a", /** @type {() => 'b'} */ n: () => 'b'} : { a: "a"; n: () => 'b'; } + + /** + * @type {"a"} + */ + a: "a", +>a : "a" +>"a" : "a" + + /** @type {() => 'b'} */ + n: () => 'b' +>n : () => 'b' +>() => 'b' : () => 'b' +>'b' : "b" + +}; +o.a +>o.a : "a" +>o : { a: "a"; n: () => "b"; } +>a : "a" + +o.n +>o.n : () => "b" +>o : { a: "a"; n: () => "b"; } +>n : () => "b" + diff --git a/tests/cases/conformance/jsdoc/typeTagOnPropertyAssignment.ts b/tests/cases/conformance/jsdoc/typeTagOnPropertyAssignment.ts new file mode 100644 index 00000000000..06d4bd87e2e --- /dev/null +++ b/tests/cases/conformance/jsdoc/typeTagOnPropertyAssignment.ts @@ -0,0 +1,13 @@ +// @noEmit: true +// @checkJs: true +// @filename: typeTagOnPropertyAssignment.js +const o = { + /** + * @type {"a"} + */ + a: "a", + /** @type {() => 'b'} */ + n: () => 'b' +}; +o.a +o.n