Skip to content

fix(49223): checker.getTypeAtLocation for ExpressionWithTypeArguments returns an error any type #49284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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