mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 01:49:41 -05:00
Merge pull request #16178 from Microsoft/master-fix13306
[Master] Fix #13306 recognize @type on property assignment
This commit is contained in:
@@ -12693,12 +12693,6 @@ namespace ts {
|
||||
if (typeNode) {
|
||||
return getTypeFromTypeNode(typeNode);
|
||||
}
|
||||
if (isInJavaScriptFile(declaration)) {
|
||||
const jsDocType = getTypeForDeclarationFromJSDocComment(declaration);
|
||||
if (jsDocType) {
|
||||
return jsDocType;
|
||||
}
|
||||
}
|
||||
if (declaration.kind === SyntaxKind.Parameter) {
|
||||
const type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
|
||||
if (type) {
|
||||
@@ -13306,6 +13300,7 @@ namespace ts {
|
||||
let patternWithComputedProperties = false;
|
||||
let hasComputedStringProperty = false;
|
||||
let hasComputedNumberProperty = false;
|
||||
const isInJSFile = isInJavaScriptFile(node);
|
||||
|
||||
let offset = 0;
|
||||
for (let i = 0; i < node.properties.length; i++) {
|
||||
@@ -13314,6 +13309,11 @@ namespace ts {
|
||||
if (memberDecl.kind === SyntaxKind.PropertyAssignment ||
|
||||
memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ||
|
||||
isObjectLiteralMethod(memberDecl)) {
|
||||
let jsdocType: Type;
|
||||
if (isInJSFile) {
|
||||
jsdocType = getTypeForDeclarationFromJSDocComment(memberDecl);
|
||||
}
|
||||
|
||||
let type: Type;
|
||||
if (memberDecl.kind === SyntaxKind.PropertyAssignment) {
|
||||
type = checkPropertyAssignment(<PropertyAssignment>memberDecl, checkMode);
|
||||
@@ -13326,6 +13326,11 @@ namespace ts {
|
||||
type = checkExpressionForMutableLocation((<ShorthandPropertyAssignment>memberDecl).name, checkMode);
|
||||
}
|
||||
|
||||
if (jsdocType) {
|
||||
checkTypeAssignableTo(type, jsdocType, memberDecl);
|
||||
type = jsdocType;
|
||||
}
|
||||
|
||||
typeFlags |= type.flags;
|
||||
const prop = createSymbol(SymbolFlags.Property | member.flags, member.name);
|
||||
if (inDestructuringPattern) {
|
||||
|
||||
@@ -2664,11 +2664,11 @@ namespace ts {
|
||||
* Gets the effective type annotation of a variable, parameter, or property. If the node was
|
||||
* parsed in a JavaScript file, gets the type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveTypeAnnotationNode(node: VariableLikeDeclaration): TypeNode {
|
||||
export function getEffectiveTypeAnnotationNode(node: VariableLikeDeclaration): TypeNode | undefined {
|
||||
if (node.type) {
|
||||
return node.type;
|
||||
}
|
||||
if (node.flags & NodeFlags.JavaScriptFile) {
|
||||
if (isInJavaScriptFile(node)) {
|
||||
return getJSDocType(node);
|
||||
}
|
||||
}
|
||||
@@ -2677,11 +2677,11 @@ namespace ts {
|
||||
* Gets the effective return type annotation of a signature. If the node was parsed in a
|
||||
* JavaScript file, gets the return type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveReturnTypeNode(node: SignatureDeclaration): TypeNode {
|
||||
export function getEffectiveReturnTypeNode(node: SignatureDeclaration): TypeNode | undefined {
|
||||
if (node.type) {
|
||||
return node.type;
|
||||
}
|
||||
if (node.flags & NodeFlags.JavaScriptFile) {
|
||||
if (isInJavaScriptFile(node)) {
|
||||
return getJSDocReturnType(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//// [0.js]
|
||||
// @ts-check
|
||||
var lol = "hello Lol"
|
||||
const obj = {
|
||||
/** @type {string|undefined} */
|
||||
foo: undefined,
|
||||
/** @type {string|undefined} */
|
||||
bar: "42",
|
||||
/** @type {function(number): number} */
|
||||
method1(n1) {
|
||||
return n1 + 42;
|
||||
},
|
||||
/** @type {string} */
|
||||
lol,
|
||||
/** @type {number} */
|
||||
['b' + 'ar1']: 42,
|
||||
/** @type {function(number): number} */
|
||||
arrowFunc: (num) => num + 42
|
||||
}
|
||||
obj.foo = 'string'
|
||||
obj.lol
|
||||
obj.bar = undefined;
|
||||
var k = obj.method1(0);
|
||||
obj.bar1 = "42";
|
||||
obj.arrowFunc(0);
|
||||
|
||||
//// [0.js]
|
||||
// @ts-check
|
||||
var lol = "hello Lol";
|
||||
var obj = (_a = {
|
||||
/** @type {string|undefined} */
|
||||
foo: undefined,
|
||||
/** @type {string|undefined} */
|
||||
bar: "42",
|
||||
/** @type {function(number): number} */
|
||||
method1: function (n1) {
|
||||
return n1 + 42;
|
||||
},
|
||||
/** @type {string} */
|
||||
lol: lol
|
||||
},
|
||||
/** @type {number} */
|
||||
_a['b' + 'ar1'] = 42,
|
||||
/** @type {function(number): number} */
|
||||
_a.arrowFunc = function (num) { return num + 42; },
|
||||
_a);
|
||||
obj.foo = 'string';
|
||||
obj.lol;
|
||||
obj.bar = undefined;
|
||||
var k = obj.method1(0);
|
||||
obj.bar1 = "42";
|
||||
obj.arrowFunc(0);
|
||||
var _a;
|
||||
@@ -0,0 +1,68 @@
|
||||
=== tests/cases/conformance/jsdoc/0.js ===
|
||||
// @ts-check
|
||||
var lol = "hello Lol"
|
||||
>lol : Symbol(lol, Decl(0.js, 1, 3))
|
||||
|
||||
const obj = {
|
||||
>obj : Symbol(obj, Decl(0.js, 2, 5))
|
||||
|
||||
/** @type {string|undefined} */
|
||||
foo: undefined,
|
||||
>foo : Symbol(foo, Decl(0.js, 2, 13))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
/** @type {string|undefined} */
|
||||
bar: "42",
|
||||
>bar : Symbol(bar, Decl(0.js, 4, 17))
|
||||
|
||||
/** @type {function(number): number} */
|
||||
method1(n1) {
|
||||
>method1 : Symbol(method1, Decl(0.js, 6, 12))
|
||||
>n1 : Symbol(n1, Decl(0.js, 8, 10))
|
||||
|
||||
return n1 + 42;
|
||||
>n1 : Symbol(n1, Decl(0.js, 8, 10))
|
||||
|
||||
},
|
||||
/** @type {string} */
|
||||
lol,
|
||||
>lol : Symbol(lol, Decl(0.js, 10, 4))
|
||||
|
||||
/** @type {number} */
|
||||
['b' + 'ar1']: 42,
|
||||
/** @type {function(number): number} */
|
||||
arrowFunc: (num) => num + 42
|
||||
>arrowFunc : Symbol(arrowFunc, Decl(0.js, 14, 20))
|
||||
>num : Symbol(num, Decl(0.js, 16, 14))
|
||||
>num : Symbol(num, Decl(0.js, 16, 14))
|
||||
}
|
||||
obj.foo = 'string'
|
||||
>obj.foo : Symbol(foo, Decl(0.js, 2, 13))
|
||||
>obj : Symbol(obj, Decl(0.js, 2, 5))
|
||||
>foo : Symbol(foo, Decl(0.js, 2, 13))
|
||||
|
||||
obj.lol
|
||||
>obj.lol : Symbol(lol, Decl(0.js, 10, 4))
|
||||
>obj : Symbol(obj, Decl(0.js, 2, 5))
|
||||
>lol : Symbol(lol, Decl(0.js, 10, 4))
|
||||
|
||||
obj.bar = undefined;
|
||||
>obj.bar : Symbol(bar, Decl(0.js, 4, 17))
|
||||
>obj : Symbol(obj, Decl(0.js, 2, 5))
|
||||
>bar : Symbol(bar, Decl(0.js, 4, 17))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var k = obj.method1(0);
|
||||
>k : Symbol(k, Decl(0.js, 21, 3))
|
||||
>obj.method1 : Symbol(method1, Decl(0.js, 6, 12))
|
||||
>obj : Symbol(obj, Decl(0.js, 2, 5))
|
||||
>method1 : Symbol(method1, Decl(0.js, 6, 12))
|
||||
|
||||
obj.bar1 = "42";
|
||||
>obj : Symbol(obj, Decl(0.js, 2, 5))
|
||||
|
||||
obj.arrowFunc(0);
|
||||
>obj.arrowFunc : Symbol(arrowFunc, Decl(0.js, 14, 20))
|
||||
>obj : Symbol(obj, Decl(0.js, 2, 5))
|
||||
>arrowFunc : Symbol(arrowFunc, Decl(0.js, 14, 20))
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
=== tests/cases/conformance/jsdoc/0.js ===
|
||||
// @ts-check
|
||||
var lol = "hello Lol"
|
||||
>lol : string
|
||||
>"hello Lol" : "hello Lol"
|
||||
|
||||
const obj = {
|
||||
>obj : { [x: string]: any; foo: string | undefined; bar: string | undefined; method1(arg0: number): number; lol: string; arrowFunc: (arg0: number) => number; }
|
||||
>{ /** @type {string|undefined} */ foo: undefined, /** @type {string|undefined} */ bar: "42", /** @type {function(number): number} */ method1(n1) { return n1 + 42; }, /** @type {string} */ lol, /** @type {number} */ ['b' + 'ar1']: 42, /** @type {function(number): number} */ arrowFunc: (num) => num + 42} : { [x: string]: any; foo: string | undefined; bar: string | undefined; method1(arg0: number): number; lol: string; arrowFunc: (arg0: number) => number; }
|
||||
|
||||
/** @type {string|undefined} */
|
||||
foo: undefined,
|
||||
>foo : string | undefined
|
||||
>undefined : undefined
|
||||
|
||||
/** @type {string|undefined} */
|
||||
bar: "42",
|
||||
>bar : string | undefined
|
||||
>"42" : "42"
|
||||
|
||||
/** @type {function(number): number} */
|
||||
method1(n1) {
|
||||
>method1 : (n1: any) => any
|
||||
>n1 : any
|
||||
|
||||
return n1 + 42;
|
||||
>n1 + 42 : any
|
||||
>n1 : any
|
||||
>42 : 42
|
||||
|
||||
},
|
||||
/** @type {string} */
|
||||
lol,
|
||||
>lol : string
|
||||
|
||||
/** @type {number} */
|
||||
['b' + 'ar1']: 42,
|
||||
>'b' + 'ar1' : string
|
||||
>'b' : "b"
|
||||
>'ar1' : "ar1"
|
||||
>42 : 42
|
||||
|
||||
/** @type {function(number): number} */
|
||||
arrowFunc: (num) => num + 42
|
||||
>arrowFunc : (arg0: number) => number
|
||||
>(num) => num + 42 : (num: any) => any
|
||||
>num : any
|
||||
>num + 42 : any
|
||||
>num : any
|
||||
>42 : 42
|
||||
}
|
||||
obj.foo = 'string'
|
||||
>obj.foo = 'string' : "string"
|
||||
>obj.foo : string | undefined
|
||||
>obj : { [x: string]: any; foo: string | undefined; bar: string | undefined; method1(arg0: number): number; lol: string; arrowFunc: (arg0: number) => number; }
|
||||
>foo : string | undefined
|
||||
>'string' : "string"
|
||||
|
||||
obj.lol
|
||||
>obj.lol : string
|
||||
>obj : { [x: string]: any; foo: string | undefined; bar: string | undefined; method1(arg0: number): number; lol: string; arrowFunc: (arg0: number) => number; }
|
||||
>lol : string
|
||||
|
||||
obj.bar = undefined;
|
||||
>obj.bar = undefined : undefined
|
||||
>obj.bar : string | undefined
|
||||
>obj : { [x: string]: any; foo: string | undefined; bar: string | undefined; method1(arg0: number): number; lol: string; arrowFunc: (arg0: number) => number; }
|
||||
>bar : string | undefined
|
||||
>undefined : undefined
|
||||
|
||||
var k = obj.method1(0);
|
||||
>k : number
|
||||
>obj.method1(0) : number
|
||||
>obj.method1 : (arg0: number) => number
|
||||
>obj : { [x: string]: any; foo: string | undefined; bar: string | undefined; method1(arg0: number): number; lol: string; arrowFunc: (arg0: number) => number; }
|
||||
>method1 : (arg0: number) => number
|
||||
>0 : 0
|
||||
|
||||
obj.bar1 = "42";
|
||||
>obj.bar1 = "42" : "42"
|
||||
>obj.bar1 : any
|
||||
>obj : { [x: string]: any; foo: string | undefined; bar: string | undefined; method1(arg0: number): number; lol: string; arrowFunc: (arg0: number) => number; }
|
||||
>bar1 : any
|
||||
>"42" : "42"
|
||||
|
||||
obj.arrowFunc(0);
|
||||
>obj.arrowFunc(0) : number
|
||||
>obj.arrowFunc : (arg0: number) => number
|
||||
>obj : { [x: string]: any; foo: string | undefined; bar: string | undefined; method1(arg0: number): number; lol: string; arrowFunc: (arg0: number) => number; }
|
||||
>arrowFunc : (arg0: number) => number
|
||||
>0 : 0
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
tests/cases/conformance/jsdoc/0.js(5,3): error TS2322: Type 'number' is not assignable to type 'string | undefined'.
|
||||
tests/cases/conformance/jsdoc/0.js(7,3): error TS2322: Type '(n1: any) => string' is not assignable to type '(arg0: number) => number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/jsdoc/0.js(11,3): error TS2322: Type '(n1: any) => string' is not assignable to type '(arg0: number) => number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/jsdoc/0.js(13,3): error TS2322: Type '(num?: string) => string' is not assignable to type '(arg0: number) => number'.
|
||||
Types of parameters 'num' and 'arg0' are incompatible.
|
||||
Type 'number' is not assignable to type 'string | undefined'.
|
||||
tests/cases/conformance/jsdoc/0.js(15,3): error TS2322: Type 'undefined' is not assignable to type 'string'.
|
||||
tests/cases/conformance/jsdoc/0.js(19,5): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/jsdoc/0.js(22,22): error TS2345: Argument of type '"0"' is not assignable to parameter of type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/0.js (7 errors) ====
|
||||
// @ts-check
|
||||
var lol;
|
||||
const obj = {
|
||||
/** @type {string|undefined} */
|
||||
bar: 42,
|
||||
~~~~~~~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string | undefined'.
|
||||
/** @type {function(number): number} */
|
||||
method1(n1) {
|
||||
~~~~~~~
|
||||
!!! error TS2322: Type '(n1: any) => string' is not assignable to type '(arg0: number) => number'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
return "42";
|
||||
},
|
||||
/** @type {function(number): number} */
|
||||
method2: (n1) => "lol",
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '(n1: any) => string' is not assignable to type '(arg0: number) => number'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
/** @type {function(number): number} */
|
||||
arrowFunc: (num="0") => num + 42,
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '(num?: string) => string' is not assignable to type '(arg0: number) => number'.
|
||||
!!! error TS2322: Types of parameters 'num' and 'arg0' are incompatible.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string | undefined'.
|
||||
/** @type {string} */
|
||||
lol
|
||||
~~~
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'string'.
|
||||
}
|
||||
lol = "string"
|
||||
/** @type {string} */
|
||||
var s = obj.method1(0);
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
/** @type {string} */
|
||||
var s1 = obj.method2("0");
|
||||
~~~
|
||||
!!! error TS2345: Argument of type '"0"' is not assignable to parameter of type 'number'.
|
||||
@@ -0,0 +1,49 @@
|
||||
//// [0.js]
|
||||
// @ts-check
|
||||
var lol;
|
||||
const obj = {
|
||||
/** @type {string|undefined} */
|
||||
bar: 42,
|
||||
/** @type {function(number): number} */
|
||||
method1(n1) {
|
||||
return "42";
|
||||
},
|
||||
/** @type {function(number): number} */
|
||||
method2: (n1) => "lol",
|
||||
/** @type {function(number): number} */
|
||||
arrowFunc: (num="0") => num + 42,
|
||||
/** @type {string} */
|
||||
lol
|
||||
}
|
||||
lol = "string"
|
||||
/** @type {string} */
|
||||
var s = obj.method1(0);
|
||||
|
||||
/** @type {string} */
|
||||
var s1 = obj.method2("0");
|
||||
|
||||
//// [0.js]
|
||||
// @ts-check
|
||||
var lol;
|
||||
var obj = {
|
||||
/** @type {string|undefined} */
|
||||
bar: 42,
|
||||
/** @type {function(number): number} */
|
||||
method1: function (n1) {
|
||||
return "42";
|
||||
},
|
||||
/** @type {function(number): number} */
|
||||
method2: function (n1) { return "lol"; },
|
||||
/** @type {function(number): number} */
|
||||
arrowFunc: function (num) {
|
||||
if (num === void 0) { num = "0"; }
|
||||
return num + 42;
|
||||
},
|
||||
/** @type {string} */
|
||||
lol: lol
|
||||
};
|
||||
lol = "string";
|
||||
/** @type {string} */
|
||||
var s = obj.method1(0);
|
||||
/** @type {string} */
|
||||
var s1 = obj.method2("0");
|
||||
@@ -0,0 +1,29 @@
|
||||
// @allowJS: true
|
||||
// @suppressOutputPathCheck: true
|
||||
// @strictNullChecks: true
|
||||
|
||||
// @filename: 0.js
|
||||
// @ts-check
|
||||
var lol = "hello Lol"
|
||||
const obj = {
|
||||
/** @type {string|undefined} */
|
||||
foo: undefined,
|
||||
/** @type {string|undefined} */
|
||||
bar: "42",
|
||||
/** @type {function(number): number} */
|
||||
method1(n1) {
|
||||
return n1 + 42;
|
||||
},
|
||||
/** @type {string} */
|
||||
lol,
|
||||
/** @type {number} */
|
||||
['b' + 'ar1']: 42,
|
||||
/** @type {function(number): number} */
|
||||
arrowFunc: (num) => num + 42
|
||||
}
|
||||
obj.foo = 'string'
|
||||
obj.lol
|
||||
obj.bar = undefined;
|
||||
var k = obj.method1(0);
|
||||
obj.bar1 = "42";
|
||||
obj.arrowFunc(0);
|
||||
@@ -0,0 +1,27 @@
|
||||
// @allowJS: true
|
||||
// @suppressOutputPathCheck: true
|
||||
// @strictNullChecks: true
|
||||
|
||||
// @filename: 0.js
|
||||
// @ts-check
|
||||
var lol;
|
||||
const obj = {
|
||||
/** @type {string|undefined} */
|
||||
bar: 42,
|
||||
/** @type {function(number): number} */
|
||||
method1(n1) {
|
||||
return "42";
|
||||
},
|
||||
/** @type {function(number): number} */
|
||||
method2: (n1) => "lol",
|
||||
/** @type {function(number): number} */
|
||||
arrowFunc: (num="0") => num + 42,
|
||||
/** @type {string} */
|
||||
lol
|
||||
}
|
||||
lol = "string"
|
||||
/** @type {string} */
|
||||
var s = obj.method1(0);
|
||||
|
||||
/** @type {string} */
|
||||
var s1 = obj.method2("0");
|
||||
Reference in New Issue
Block a user