Fix getEffectiveTypeAnnotationNode

Prevent it from using the (return) type of a function.  Could also check
the condition before calling the function, but there are two places that
need the check, and OTOH, all calls check the result so returning
`undefined` should work.

(This problem was introduced in PR#32553.)

Fixes #33741.
This commit is contained in:
Eli Barzilay 2020-01-03 15:30:41 -05:00
parent 5cc58deb57
commit d6c05a1358
5 changed files with 169 additions and 1 deletions

View File

@ -3865,9 +3865,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.
* parsed in a JavaScript file, gets the type annotation from JSDoc. Also gets the type of
* functions only the JSDoc case.
*/
export function getEffectiveTypeAnnotationNode(node: Node): TypeNode | undefined {
if (!isInJSFile(node) && isFunctionDeclaration(node)) return undefined;
const type = (node as HasType).type;
if (type || !isInJSFile(node)) return type;
return isJSDocPropertyLikeTag(node) ? node.typeExpression && node.typeExpression.type : getJSDocType(node);

View File

@ -0,0 +1,42 @@
//// [propertyAssignmentUseParentType3.ts]
// don't use the parent type if it's a function declaration (#33741)
function foo1(): number {
return 123;
}
foo1.toFixed = "";
function foo2(): any[] {
return [];
}
foo2.join = "";
function foo3(): string {
return "";
}
foo3.trim = "";
function foo4(): ({x: number}) {
return {x: 123};
}
foo4.x = "456";
//// [propertyAssignmentUseParentType3.js]
// don't use the parent type if it's a function declaration (#33741)
function foo1() {
return 123;
}
foo1.toFixed = "";
function foo2() {
return [];
}
foo2.join = "";
function foo3() {
return "";
}
foo3.trim = "";
function foo4() {
return { x: 123 };
}
foo4.x = "456";

View File

@ -0,0 +1,45 @@
=== tests/cases/conformance/salsa/propertyAssignmentUseParentType3.ts ===
// don't use the parent type if it's a function declaration (#33741)
function foo1(): number {
>foo1 : Symbol(foo1, Decl(propertyAssignmentUseParentType3.ts, 0, 0), Decl(propertyAssignmentUseParentType3.ts, 4, 1))
return 123;
}
foo1.toFixed = "";
>foo1.toFixed : Symbol(foo1.toFixed, Decl(propertyAssignmentUseParentType3.ts, 4, 1))
>foo1 : Symbol(foo1, Decl(propertyAssignmentUseParentType3.ts, 0, 0), Decl(propertyAssignmentUseParentType3.ts, 4, 1))
>toFixed : Symbol(foo1.toFixed, Decl(propertyAssignmentUseParentType3.ts, 4, 1))
function foo2(): any[] {
>foo2 : Symbol(foo2, Decl(propertyAssignmentUseParentType3.ts, 5, 18), Decl(propertyAssignmentUseParentType3.ts, 9, 1))
return [];
}
foo2.join = "";
>foo2.join : Symbol(foo2.join, Decl(propertyAssignmentUseParentType3.ts, 9, 1))
>foo2 : Symbol(foo2, Decl(propertyAssignmentUseParentType3.ts, 5, 18), Decl(propertyAssignmentUseParentType3.ts, 9, 1))
>join : Symbol(foo2.join, Decl(propertyAssignmentUseParentType3.ts, 9, 1))
function foo3(): string {
>foo3 : Symbol(foo3, Decl(propertyAssignmentUseParentType3.ts, 10, 15), Decl(propertyAssignmentUseParentType3.ts, 14, 1))
return "";
}
foo3.trim = "";
>foo3.trim : Symbol(foo3.trim, Decl(propertyAssignmentUseParentType3.ts, 14, 1))
>foo3 : Symbol(foo3, Decl(propertyAssignmentUseParentType3.ts, 10, 15), Decl(propertyAssignmentUseParentType3.ts, 14, 1))
>trim : Symbol(foo3.trim, Decl(propertyAssignmentUseParentType3.ts, 14, 1))
function foo4(): ({x: number}) {
>foo4 : Symbol(foo4, Decl(propertyAssignmentUseParentType3.ts, 15, 15), Decl(propertyAssignmentUseParentType3.ts, 19, 1))
>x : Symbol(x, Decl(propertyAssignmentUseParentType3.ts, 17, 19))
return {x: 123};
>x : Symbol(x, Decl(propertyAssignmentUseParentType3.ts, 18, 12))
}
foo4.x = "456";
>foo4.x : Symbol(foo4.x, Decl(propertyAssignmentUseParentType3.ts, 19, 1))
>foo4 : Symbol(foo4, Decl(propertyAssignmentUseParentType3.ts, 15, 15), Decl(propertyAssignmentUseParentType3.ts, 19, 1))
>x : Symbol(foo4.x, Decl(propertyAssignmentUseParentType3.ts, 19, 1))

View File

@ -0,0 +1,58 @@
=== tests/cases/conformance/salsa/propertyAssignmentUseParentType3.ts ===
// don't use the parent type if it's a function declaration (#33741)
function foo1(): number {
>foo1 : typeof foo1
return 123;
>123 : 123
}
foo1.toFixed = "";
>foo1.toFixed = "" : ""
>foo1.toFixed : string
>foo1 : typeof foo1
>toFixed : string
>"" : ""
function foo2(): any[] {
>foo2 : typeof foo2
return [];
>[] : undefined[]
}
foo2.join = "";
>foo2.join = "" : ""
>foo2.join : string
>foo2 : typeof foo2
>join : string
>"" : ""
function foo3(): string {
>foo3 : typeof foo3
return "";
>"" : ""
}
foo3.trim = "";
>foo3.trim = "" : ""
>foo3.trim : string
>foo3 : typeof foo3
>trim : string
>"" : ""
function foo4(): ({x: number}) {
>foo4 : typeof foo4
>x : number
return {x: 123};
>{x: 123} : { x: number; }
>x : number
>123 : 123
}
foo4.x = "456";
>foo4.x = "456" : "456"
>foo4.x : string
>foo4 : typeof foo4
>x : string
>"456" : "456"

View File

@ -0,0 +1,21 @@
// don't use the parent type if it's a function declaration (#33741)
function foo1(): number {
return 123;
}
foo1.toFixed = "";
function foo2(): any[] {
return [];
}
foo2.join = "";
function foo3(): string {
return "";
}
foo3.trim = "";
function foo4(): ({x: number}) {
return {x: 123};
}
foo4.x = "456";