Skip to content
Merged
14 changes: 14 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6671,6 +6671,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
else {
const isInstantiationExpressionType = !!(getObjectFlags(type) & ObjectFlags.InstantiationExpressionType);
if (isInstantiationExpressionType) {
const instantiationExpressionType = type as InstantiationExpressionType;
if (isTypeQueryNode(instantiationExpressionType.node)) {
const typeNode = serializeExistingTypeNode(context, instantiationExpressionType.node);
if (typeNode) {
return typeNode;
}
}
if (context.visitedTypes?.has(typeId)) {
return createElidedInformationPlaceholder(context);
}
return visitAndTransformType(type, createTypeNodeFromObjectType);
}
// Anonymous types without a symbol are never circular.
return createTypeNodeFromObjectType(type);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/arrayTypeOfTypeOf.types
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ var xs2: typeof Array;
>Array : ArrayConstructor

var xs3: typeof Array<number>;
>xs3 : { (arrayLength: number): number[]; (...items: number[]): number[]; new (arrayLength: number): number[]; new (...items: number[]): number[]; isArray(arg: any): arg is any[]; readonly prototype: any[]; }
>xs3 : typeof Array<number>
>Array : ArrayConstructor

var xs4: typeof Array<typeof x>;
>xs4 : { (arrayLength: number): number[]; (...items: number[]): number[]; new (arrayLength: number): number[]; new (...items: number[]): number[]; isArray(arg: any): arg is any[]; readonly prototype: any[]; }
>xs4 : typeof Array<typeof x>
>Array : ArrayConstructor
>x : number

11 changes: 11 additions & 0 deletions tests/baselines/reference/circularInstantiationExpression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//// [circularInstantiationExpression.ts]
declare function foo<T>(t: T): typeof foo<T>;
foo("");


//// [circularInstantiationExpression.js]
foo("");


//// [circularInstantiationExpression.d.ts]
declare function foo<T>(t: T): typeof foo<T>;
12 changes: 12 additions & 0 deletions tests/baselines/reference/circularInstantiationExpression.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
=== tests/cases/compiler/circularInstantiationExpression.ts ===
declare function foo<T>(t: T): typeof foo<T>;
>foo : Symbol(foo, Decl(circularInstantiationExpression.ts, 0, 0))
>T : Symbol(T, Decl(circularInstantiationExpression.ts, 0, 21))
>t : Symbol(t, Decl(circularInstantiationExpression.ts, 0, 24))
>T : Symbol(T, Decl(circularInstantiationExpression.ts, 0, 21))
>foo : Symbol(foo, Decl(circularInstantiationExpression.ts, 0, 0))
>T : Symbol(T, Decl(circularInstantiationExpression.ts, 0, 21))

foo("");
>foo : Symbol(foo, Decl(circularInstantiationExpression.ts, 0, 0))

11 changes: 11 additions & 0 deletions tests/baselines/reference/circularInstantiationExpression.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=== tests/cases/compiler/circularInstantiationExpression.ts ===
declare function foo<T>(t: T): typeof foo<T>;
>foo : <T>(t: T) => typeof foo<T>
>t : T
>foo : <T>(t: T) => typeof foo<T>

foo("");
>foo("") : (t: string) => any
>foo : <T>(t: T) => (t: T) => any
>"" : ""

16 changes: 8 additions & 8 deletions tests/baselines/reference/expressionWithJSDocTypeArguments.types
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ const ComeOnFoo = foo<?string?>;
>foo : <T>(x: T) => T

type TWhatFoo = typeof foo<?>;
>TWhatFoo : (x: any) => any
>TWhatFoo : typeof foo<unknown>
>foo : <T>(x: T) => T

type THuhFoo = typeof foo<string?>;
>THuhFoo : (x: string | null) => string | null
>THuhFoo : typeof foo<string | null>
>foo : <T>(x: T) => T

type TNopeFoo = typeof foo<?string>;
>TNopeFoo : (x: string | null) => string | null
>TNopeFoo : typeof foo<string | null>
>foo : <T>(x: T) => T

type TComeOnFoo = typeof foo<?string?>;
>TComeOnFoo : (x: string | null) => string | null
>TComeOnFoo : typeof foo<(string | null) | null>
>foo : <T>(x: T) => T

const WhatBar = Bar<?>;
Expand All @@ -69,18 +69,18 @@ const ComeOnBar = Bar<?string?>;
>Bar : typeof Bar

type TWhatBar = typeof Bar<?>;
>TWhatBar : { new (x: any): Bar<any>; prototype: Bar<any>; }
>TWhatBar : typeof Bar<unknown>
>Bar : typeof Bar

type THuhBar = typeof Bar<string?>;
>THuhBar : { new (x: string | null): Bar<string | null>; prototype: Bar<any>; }
>THuhBar : typeof Bar<string | null>
>Bar : typeof Bar

type TNopeBar = typeof Bar<?string>;
>TNopeBar : { new (x: string | null): Bar<string | null>; prototype: Bar<any>; }
>TNopeBar : typeof Bar<string | null>
>Bar : typeof Bar

type TComeOnBar = typeof Bar<?string?>;
>TComeOnBar : { new (x: string | null): Bar<string | null>; prototype: Bar<any>; }
>TComeOnBar : typeof Bar<(string | null) | null>
>Bar : typeof Bar

22 changes: 11 additions & 11 deletions tests/baselines/reference/instantiationExpressions.types
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ type T10 = typeof fx<>; // Error
>fx : { <T>(x: T): T; <T>(x: T, n: number): T; <T, U>(t: [T, U]): [T, U]; }

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

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

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

function f2() {
Expand All @@ -76,11 +76,11 @@ type T20 = typeof Array<>; // Error
>Array : ArrayConstructor

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

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

declare class C<T> {
Expand Down Expand Up @@ -439,7 +439,7 @@ function makeBox<T>(value: T) {
}

type BoxFunc<T> = typeof makeBox<T>; // (value: T) => { value: T }
>BoxFunc : (value: T) => { value: T; }
>BoxFunc : typeof makeBox<T>
>makeBox : <T>(value: T) => { value: T; }

type StringBoxFunc = BoxFunc<string>; // (value: string) => { value: string }
Expand Down Expand Up @@ -469,7 +469,7 @@ declare const g1: {
}

type T30<V> = typeof g1<V>; // { (a: V) => { a: V }; new (b: V) => { b: V }; }
>T30 : { (a: V): { a: V; }; new (b: V): { b: V; }; }
>T30 : typeof g1<V>
>g1 : { <T>(a: T): { a: T; }; new <U>(b: U): { b: U; }; }

type T31<A> = ReturnType<T30<A>>; // { a: A }
Expand All @@ -489,11 +489,11 @@ declare const g2: {
}

type T40<U extends string> = typeof g2<U>; // Error
>T40 : { (a: U): U; new <T extends number>(b: T): T; }
>T40 : typeof g2<U>
>g2 : { <T extends string>(a: T): T; new <T extends number>(b: T): T; }

type T41<U extends number> = typeof g2<U>; // Error
>T41 : { <T extends string>(a: T): T; new (b: U): U; }
>T41 : typeof g2<U>
>g2 : { <T extends string>(a: T): T; new <T extends number>(b: T): T; }

declare const g3: {
Expand All @@ -507,10 +507,10 @@ declare const g3: {
}

type T50<U extends string> = typeof g3<U>; // (a: U) => U
>T50 : (a: U) => U
>T50 : typeof g3<U>
>g3 : { <T extends string>(a: T): T; new <T extends number, Q>(b: T): T; }

type T51<U extends number> = typeof g3<U, any>; // (b: U) => U
>T51 : new (b: U) => U
>T51 : typeof g3<U, any>
>g3 : { <T extends string>(a: T): T; new <T extends number, Q>(b: T): T; }

Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
=== /tests/cases/fourslash/quickInfoCircularInstantiationExpression.ts ===
// declare function foo<T>(t: T): typeof foo<T>;
// foo("");
// ^^^
// | ----------------------------------------------------------------------
// | function foo<string>(t: string): (t: string) => ...
// | ----------------------------------------------------------------------

[
{
"marker": {
"fileName": "/tests/cases/fourslash/quickInfoCircularInstantiationExpression.ts",
"position": 46,
"name": ""
},
"item": {
"kind": "function",
"kindModifiers": "declare",
"textSpan": {
"start": 46,
"length": 3
},
"displayParts": [
{
"text": "function",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "foo",
"kind": "functionName"
},
{
"text": "<",
"kind": "punctuation"
},
{
"text": "string",
"kind": "keyword"
},
{
"text": ">",
"kind": "punctuation"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": "t",
"kind": "parameterName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "string",
"kind": "keyword"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": "t",
"kind": "parameterName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "string",
"kind": "keyword"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "=>",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "...",
"kind": "text"
}
],
"documentation": []
}
}
]
14 changes: 14 additions & 0 deletions tests/baselines/reference/selfReferentialFunctionType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//// [selfReferentialFunctionType.ts]
declare function f<T>(args: typeof f<T>): T;
declare function g<T = typeof g>(args: T): T;
declare function h<T>(): typeof h<T>;


//// [selfReferentialFunctionType.js]
"use strict";


//// [selfReferentialFunctionType.d.ts]
declare function f<T>(args: typeof f<T>): T;
declare function g<T = typeof g>(args: T): T;
declare function h<T>(): typeof h<T>;
23 changes: 23 additions & 0 deletions tests/baselines/reference/selfReferentialFunctionType.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
=== tests/cases/compiler/selfReferentialFunctionType.ts ===
declare function f<T>(args: typeof f<T>): T;
>f : Symbol(f, Decl(selfReferentialFunctionType.ts, 0, 0))
>T : Symbol(T, Decl(selfReferentialFunctionType.ts, 0, 19))
>args : Symbol(args, Decl(selfReferentialFunctionType.ts, 0, 22))
>f : Symbol(f, Decl(selfReferentialFunctionType.ts, 0, 0))
>T : Symbol(T, Decl(selfReferentialFunctionType.ts, 0, 19))
>T : Symbol(T, Decl(selfReferentialFunctionType.ts, 0, 19))

declare function g<T = typeof g>(args: T): T;
>g : Symbol(g, Decl(selfReferentialFunctionType.ts, 0, 44))
>T : Symbol(T, Decl(selfReferentialFunctionType.ts, 1, 19))
>g : Symbol(g, Decl(selfReferentialFunctionType.ts, 0, 44))
>args : Symbol(args, Decl(selfReferentialFunctionType.ts, 1, 33))
>T : Symbol(T, Decl(selfReferentialFunctionType.ts, 1, 19))
>T : Symbol(T, Decl(selfReferentialFunctionType.ts, 1, 19))

declare function h<T>(): typeof h<T>;
>h : Symbol(h, Decl(selfReferentialFunctionType.ts, 1, 45))
>T : Symbol(T, Decl(selfReferentialFunctionType.ts, 2, 19))
>h : Symbol(h, Decl(selfReferentialFunctionType.ts, 1, 45))
>T : Symbol(T, Decl(selfReferentialFunctionType.ts, 2, 19))

15 changes: 15 additions & 0 deletions tests/baselines/reference/selfReferentialFunctionType.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
=== tests/cases/compiler/selfReferentialFunctionType.ts ===
declare function f<T>(args: typeof f<T>): T;
>f : <T>(args: typeof f<T>) => T
>args : typeof f<T>
>f : <T>(args: typeof f<T>) => T

declare function g<T = typeof g>(args: T): T;
>g : <T = typeof g>(args: T) => T
>g : <T = typeof g>(args: T) => T
>args : T

declare function h<T>(): typeof h<T>;
>h : <T>() => typeof h<T>
>h : <T>() => typeof h<T>

3 changes: 3 additions & 0 deletions tests/cases/compiler/circularInstantiationExpression.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @declaration: true
declare function foo<T>(t: T): typeof foo<T>;
foo("");
6 changes: 6 additions & 0 deletions tests/cases/compiler/selfReferentialFunctionType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @strict: true
// @declaration: true

declare function f<T>(args: typeof f<T>): T;
declare function g<T = typeof g>(args: T): T;
declare function h<T>(): typeof h<T>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// <reference path="fourslash.ts" />

////declare function foo<T>(t: T): typeof foo<T>;
/////**/foo("");

verify.baselineQuickInfo();