Skip to content

Commit

Permalink
fix(49223): checker.getTypeAtLocation for ExpressionWithTypeArguments…
Browse files Browse the repository at this point in the history
… returns an error any type (#49284) (#49369)

* fix(49223): handle ExpressionWithTypeArguments nodes in isExpressionNode

* Update src/compiler/utilities.ts

* Just use `!isHeritageClause(node.parent)`.

Co-authored-by: Daniel Rosenwasser <[email protected]>

Co-authored-by: Oleksandr T <[email protected]>
  • Loading branch information
DanielRosenwasser and a-tarasyuk authored Jun 3, 2022
1 parent 3bf0d30 commit 3ce08c6
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2016,6 +2016,8 @@ namespace ts {
case SyntaxKind.AwaitExpression:
case SyntaxKind.MetaProperty:
return true;
case SyntaxKind.ExpressionWithTypeArguments:
return !isHeritageClause(node.parent);
case SyntaxKind.QualifiedName:
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
Expand Down
24 changes: 24 additions & 0 deletions src/testRunner/unittests/publicApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,30 @@ describe("unittests:: Public APIs:: getTypeAtLocation", () => {
assert.equal(type.flags, ts.TypeFlags.Any);
});

it("works on ExpressionWithTypeArguments", () => {
const content = `
function fn<T>(value: T) {
return { value };
}
const foo = fn<string>;
`;
const host = new fakes.CompilerHost(vfs.createFromFileSystem(
Harness.IO,
/*ignoreCase*/ true,
{ documents: [new documents.TextDocument("/file.ts", content)], cwd: "/" }));

const program = ts.createProgram({
host,
rootNames: ["/file.ts"],
options: { noLib: true }
});

const checker = program.getTypeChecker();
const file = program.getSourceFile("/file.ts")!;
const [declaration] = (ts.findLast(file.statements, ts.isVariableStatement) as ts.VariableStatement).declarationList.declarations;
assert.equal(checker.getTypeAtLocation(declaration.initializer!).flags, ts.TypeFlags.Object);
});

it("returns an errorType for VariableDeclaration with BindingPattern name", () => {
const content = "const foo = [1];\n" + "const [a] = foo;";

Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/genericCallWithoutArgs.types
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ function f<X, Y>(x: X, y: Y) {

f<number,string>.
>f<number,string>. : any
>f<number,string> : (x: number, y: string) => void
>f : <X, Y>(x: X, y: Y) => void
> : any

3 changes: 3 additions & 0 deletions tests/baselines/reference/importWithTypeArguments.types
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
=== tests/cases/conformance/types/import/importWithTypeArguments.ts ===
import<T>
>import<T> : any

const a = import<string, number>
>a : any
>import<string, number> : any

13 changes: 13 additions & 0 deletions tests/baselines/reference/instantiationExpressionErrors.types
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,34 @@ declare let f: { <T>(): T, g<U>(): U };

const a1 = f<number>; // { (): number; g<U>(): U; }
>a1 : { (): number; g<U>(): U; }
>f<number> : { (): number; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }

const a2 = f.g<number>; // () => number
>a2 : () => number
>f.g<number> : () => number
>f.g : <U>() => U
>f : { <T>(): T; g<U>(): U; }
>g : <U>() => U

const a3 = f<number>.g; // <U>() => U
>a3 : <U>() => U
>f<number>.g : <U>() => U
>f<number> : { (): number; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }
>g : <U>() => U

const a4 = f<number>.g<number>; // () => number
>a4 : () => number
>f<number>.g<number> : () => number
>f<number>.g : <U>() => U
>f<number> : { (): number; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }
>g : <U>() => U

const a5 = f['g']<number>; // () => number
>a5 : () => number
>f['g']<number> : () => number
>f['g'] : <U>() => U
>f : { <T>(): T; g<U>(): U; }
>'g' : "g"
Expand All @@ -48,6 +54,7 @@ const a7 = (f<number>)['g'];
>a7 : <U>() => U
>(f<number>)['g'] : <U>() => U
>(f<number>) : { (): number; g<U>(): U; }
>f<number> : { (): number; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }
>'g' : "g"

Expand All @@ -64,7 +71,9 @@ const a8 = f<number><number>; // Relational operator error

const a9 = (f<number>)<number>; // Error, no applicable signatures
>a9 : { g<U>(): U; }
>(f<number>)<number> : { g<U>(): U; }
>(f<number>) : { (): number; g<U>(): U; }
>f<number> : { (): number; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }

// Type arguments with `?.` token
Expand All @@ -82,11 +91,13 @@ const b2 = f?.<number>();
const b3 = f<number>?.();
>b3 : number
>f<number>?.() : number
>f<number> : { (): number; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }

const b4 = f<number>?.<number>(); // Error, expected no type arguments
>b4 : number
>f<number>?.<number>() : number
>f<number> : { (): number; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }

// Parsed as function call, even though this differs from JavaScript
Expand Down Expand Up @@ -116,6 +127,7 @@ true;

const x3 = f<true>;
>x3 : { (): true; g<U>(): U; }
>f<true> : { (): true; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }
>true : true

Expand All @@ -126,6 +138,7 @@ true;

const x4 = f<true>
>x4 : { (): true; g<U>(): U; }
>f<true> : { (): true; g<U>(): U; }
>f : { <T>(): T; g<U>(): U; }
>true : true

Expand Down
34 changes: 34 additions & 0 deletions tests/baselines/reference/instantiationExpressions.types
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ function f1() {

let f0 = fx<>; // Error
>f0 : { <T>(x: T): T; <T>(x: T, n: number): T; <T, U>(t: [T, U]): [T, U]; }
>fx<> : { <T>(x: T): T; <T>(x: T, n: number): T; <T, U>(t: [T, U]): [T, U]; }
>fx : { <T>(x: T): T; <T>(x: T, n: number): T; <T, U>(t: [T, U]): [T, U]; }

let f1 = fx<string>; // { (x: string): string; (x: string, n: number): string; }
>f1 : { (x: string): string; (x: string, n: number): string; }
>fx<string> : { (x: string): string; (x: string, n: number): string; }
>fx : { <T>(x: T): T; <T>(x: T, n: number): T; <T, U>(t: [T, U]): [T, U]; }

let f2 = fx<string, number>; // (t: [string, number]) => [string, number]
>f2 : (t: [string, number]) => [string, number]
>fx<string, number> : (t: [string, number]) => [string, number]
>fx : { <T>(x: T): T; <T>(x: T, n: number): T; <T, U>(t: [T, U]): [T, U]; }

let f3 = fx<string, number, boolean>; // Error
>f3 : {}
>fx<string, number, boolean> : {}
>fx : { <T>(x: T): T; <T>(x: T, n: number): T; <T, U>(t: [T, U]): [T, U]; }
}

Expand All @@ -53,14 +57,17 @@ function f2() {

const A0 = Array<>; // Error
>A0 : ArrayConstructor
>Array<> : ArrayConstructor
>Array : ArrayConstructor

const A1 = Array<string>; // new (...) => string[]
>A1 : { (arrayLength: number): string[]; (...items: string[]): string[]; new (arrayLength: number): string[]; new (...items: string[]): string[]; isArray(arg: any): arg is any[]; readonly prototype: any[]; }
>Array<string> : { (arrayLength: number): string[]; (...items: string[]): string[]; new (arrayLength: number): string[]; new (...items: string[]): string[]; isArray(arg: any): arg is any[]; readonly prototype: any[]; }
>Array : ArrayConstructor

const A2 = Array<string, number>; // Error
>A2 : { isArray(arg: any): arg is any[]; readonly prototype: any[]; }
>Array<string, number> : { isArray(arg: any): arg is any[]; readonly prototype: any[]; }
>Array : ArrayConstructor
}

Expand Down Expand Up @@ -92,10 +99,12 @@ function f3() {

let c1 = C<string>; // { new (x: string): C<string>; f<U>(x: U): T[]; prototype: C<any>; }
>c1 : { new (x: string): C<string>; prototype: C<any>; f<U>(x: U): U[]; }
>C<string> : { new (x: string): C<string>; prototype: C<any>; f<U>(x: U): U[]; }
>C : typeof C

let f1 = C.f<string>; // (x: string) => string[]
>f1 : (x: string) => string[]
>C.f<string> : (x: string) => string[]
>C.f : <U>(x: U) => U[]
>C : typeof C
>f : <U>(x: U) => U[]
Expand All @@ -110,6 +119,7 @@ function f10(f: { <T>(a: T): T, <U>(a: U, b: number): U[] }) {

let fs = f<string>; // { (a: string): string; (a: string, b: number): string[]; }
>fs : { (a: string): string; (a: string, b: number): string[]; }
>f<string> : { (a: string): string; (a: string, b: number): string[]; }
>f : { <T>(a: T): T; <U>(a: U, b: number): U[]; }
}

Expand All @@ -122,6 +132,7 @@ function f11(f: { <T>(a: T): T, (a: string, b: number): string[] }) {

let fs = f<string>; // (a: string) => string
>fs : (a: string) => string
>f<string> : (a: string) => string
>f : { <T>(a: T): T; (a: string, b: number): string[]; }
}

Expand All @@ -133,6 +144,7 @@ function f12(f: { <T>(a: T): T, x: string }) {

let fs = f<string>; // { (a: string): string; x: string; }
>fs : { (a: string): string; x: string; }
>f<string> : { (a: string): string; x: string; }
>f : { <T>(a: T): T; x: string; }
}

Expand All @@ -144,6 +156,7 @@ function f13(f: { x: string, y: string }) {

let fs = f<string>; // Error, no applicable signatures
>fs : { x: string; y: string; }
>f<string> : { x: string; y: string; }
>f : { x: string; y: string; }
}

Expand All @@ -156,6 +169,7 @@ function f14(f: { new <T>(a: T): T, new <U>(a: U, b: number): U[] }) {

let fs = f<string>; // { new (a: string): string; new (a: string, b: number): string[]; }
>fs : { new (a: string): string; new (a: string, b: number): string[]; }
>f<string> : { new (a: string): string; new (a: string, b: number): string[]; }
>f : { new <T>(a: T): T; new <U>(a: U, b: number): U[]; }
}

Expand All @@ -168,6 +182,7 @@ function f15(f: { new <T>(a: T): T, <U>(a: U, b: number): U[] }) {

let fs = f<string>; // { new (a: string): string; (a: string, b: number): string[]; }
>fs : { (a: string, b: number): string[]; new (a: string): string; }
>f<string> : { (a: string, b: number): string[]; new (a: string): string; }
>f : { <U>(a: U, b: number): U[]; new <T>(a: T): T; }
}

Expand All @@ -180,6 +195,7 @@ function f16(f: { new <T>(a: T): T, (a: string, b: number): string[] }) {

let fs = f<string>; // new (a: string) => string
>fs : new (a: string) => string
>f<string> : new (a: string) => string
>f : { (a: string, b: number): string[]; new <T>(a: T): T; }
}

Expand All @@ -192,6 +208,7 @@ function f17(f: { <T>(a: T): T, new (a: string, b: number): string[] }) {

let fs = f<string>; // (a: string) => string
>fs : (a: string) => string
>f<string> : (a: string) => string
>f : { <T>(a: T): T; new (a: string, b: number): string[]; }
}

Expand All @@ -204,6 +221,7 @@ function f20(f: (<T>(a: T) => T) & (<U>(a: U, b: number) => U[])) {

let fs = f<string>; // ((a: string) => string) & ((a: string, b: number) => string[]])
>fs : ((a: string) => string) & ((a: string, b: number) => string[])
>f<string> : ((a: string) => string) & ((a: string, b: number) => string[])
>f : (<T>(a: T) => T) & (<U>(a: U, b: number) => U[])
}

Expand All @@ -216,6 +234,7 @@ function f21(f: (<T>(a: T) => T) & ((a: string, b: number) => string[])) {

let fs = f<string>; // (a: string) => string
>fs : (a: string) => string
>f<string> : (a: string) => string
>f : (<T>(a: T) => T) & ((a: string, b: number) => string[])
}

Expand All @@ -227,6 +246,7 @@ function f22(f: (<T>(a: T) => T) & { x: string }) {

let fs = f<string>; // ((a: string) => string) & { x: string }
>fs : ((a: string) => string) & { x: string; }
>f<string> : ((a: string) => string) & { x: string; }
>f : (<T>(a: T) => T) & { x: string; }
}

Expand All @@ -238,6 +258,7 @@ function f23(f: { x: string } & { y: string }) {

let fs = f<string>; // Error, no applicable signatures
>fs : { x: string; } & { y: string; }
>f<string> : { x: string; } & { y: string; }
>f : { x: string; } & { y: string; }
}

Expand All @@ -250,6 +271,7 @@ function f24(f: (new <T>(a: T) => T) & (new <U>(a: U, b: number) => U[])) {

let fs = f<string>; // (new (a: string) => string) & ((a: string, b: number) => string[]])
>fs : (new (a: string) => string) & (new (a: string, b: number) => string[])
>f<string> : (new (a: string) => string) & (new (a: string, b: number) => string[])
>f : (new <T>(a: T) => T) & (new <U>(a: U, b: number) => U[])
}

Expand All @@ -262,6 +284,7 @@ function f25(f: (new <T>(a: T) => T) & (<U>(a: U, b: number) => U[])) {

let fs = f<string>; // (new (a: string) => string) & ((a: string, b: number) => string[]])
>fs : (new (a: string) => string) & ((a: string, b: number) => string[])
>f<string> : (new (a: string) => string) & ((a: string, b: number) => string[])
>f : (new <T>(a: T) => T) & (<U>(a: U, b: number) => U[])
}

Expand All @@ -274,6 +297,7 @@ function f26(f: (new <T>(a: T) => T) & ((a: string, b: number) => string[])) {

let fs = f<string>; // new (a: string) => string
>fs : new (a: string) => string
>f<string> : new (a: string) => string
>f : (new <T>(a: T) => T) & ((a: string, b: number) => string[])
}

Expand All @@ -286,6 +310,7 @@ function f27(f: (<T>(a: T) => T) & (new (a: string, b: number) => string[])) {

let fs = f<string>; // (a: string) => string
>fs : (a: string) => string
>f<string> : (a: string) => string
>f : (<T>(a: T) => T) & (new (a: string, b: number) => string[])
}

Expand All @@ -298,6 +323,7 @@ function f30(f: (<T>(a: T) => T) | (<U>(a: U, b: number) => U[])) {

let fs = f<string>; // ((a: string) => string) | ((a: string, b: number) => string[]])
>fs : ((a: string) => string) | ((a: string, b: number) => string[])
>f<string> : ((a: string) => string) | ((a: string, b: number) => string[])
>f : (<T>(a: T) => T) | (<U>(a: U, b: number) => U[])
}

Expand All @@ -310,6 +336,7 @@ function f31(f: (<T>(a: T) => T) | ((a: string, b: number) => string[])) {

let fs = f<string>; // Error, '(a: string, b: number) => string[]' has no applicable signatures
>fs : ((a: string) => string) | {}
>f<string> : ((a: string) => string) | {}
>f : (<T>(a: T) => T) | ((a: string, b: number) => string[])
}

Expand All @@ -321,6 +348,7 @@ function f32(f: (<T>(a: T) => T) | { x: string }) {

let fs = f<string>; // ((a: string) => string) | { x: string }
>fs : { x: string; } | ((a: string) => string)
>f<string> : { x: string; } | ((a: string) => string)
>f : { x: string; } | (<T>(a: T) => T)
}

Expand All @@ -332,6 +360,7 @@ function f33(f: { x: string } | { y: string }) {

let fs = f<string>; // Error, no applicable signatures
>fs : { x: string; } | { y: string; }
>f<string> : { x: string; } | { y: string; }
>f : { x: string; } | { y: string; }
}

Expand All @@ -344,6 +373,7 @@ function f34(f: (new <T>(a: T) => T) | (new <U>(a: U, b: number) => U[])) {

let fs = f<string>; // (new (a: string) => string) | ((a: string, b: number) => string[]])
>fs : (new (a: string) => string) | (new (a: string, b: number) => string[])
>f<string> : (new (a: string) => string) | (new (a: string, b: number) => string[])
>f : (new <T>(a: T) => T) | (new <U>(a: U, b: number) => U[])
}

Expand All @@ -356,6 +386,7 @@ function f35(f: (new <T>(a: T) => T) | (<U>(a: U, b: number) => U[])) {

let fs = f<string>; // (new (a: string) => string) | ((a: string, b: number) => string[]])
>fs : (new (a: string) => string) | ((a: string, b: number) => string[])
>f<string> : (new (a: string) => string) | ((a: string, b: number) => string[])
>f : (new <T>(a: T) => T) | (<U>(a: U, b: number) => U[])
}

Expand All @@ -368,6 +399,7 @@ function f36(f: (new <T>(a: T) => T) | ((a: string, b: number) => string[])) {

let fs = f<string>; // Error, '(a: string, b: number) => string[]' has no applicable signatures
>fs : (new (a: string) => string) | {}
>f<string> : (new (a: string) => string) | {}
>f : (new <T>(a: T) => T) | ((a: string, b: number) => string[])
}

Expand All @@ -380,6 +412,7 @@ function f37(f: (<T>(a: T) => T) | (new (a: string, b: number) => string[])) {

let fs = f<string>; // Error, 'new (a: string, b: number) => string[]' has no applicable signatures
>fs : ((a: string) => string) | {}
>f<string> : ((a: string) => string) | {}
>f : (<T>(a: T) => T) | (new (a: string, b: number) => string[])
}

Expand All @@ -392,6 +425,7 @@ function f38<T extends (<A>(x: A) => A) | (<B>(x: B) => B[]), U>(f: T | U | (<C>

let fs = f<string>; // U | ((x: string) => string) | ((x: string) => string[]) | ((x: string) => string[][])
>fs : U | ((x: string) => string) | ((x: string) => string[]) | ((x: string) => string[][])
>f<string> : U | ((x: string) => string) | ((x: string) => string[]) | ((x: string) => string[][])
>f : T | U | (<C>(x: C) => C[][])
}

Expand Down
Loading

0 comments on commit 3ce08c6

Please sign in to comment.