diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5af3c9e9c51eb..cf0f63f739fb2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3199,7 +3199,8 @@ namespace ts { getCurrentDirectory: host.getCurrentDirectory && (() => host.getCurrentDirectory!()) } : undefined }, encounteredError: false, - visitedSymbols: undefined, + visitedTypes: undefined, + symbolDepth: undefined, inferTypeParameters: undefined, approximateLength: 0 }; @@ -3430,6 +3431,7 @@ namespace ts { } function createAnonymousTypeNode(type: ObjectType): TypeNode { + const typeId = "" + type.id; const symbol = type.symbol; let id: string; if (symbol) { @@ -3446,7 +3448,7 @@ namespace ts { shouldWriteTypeOfFunctionSymbol()) { return symbolToTypeNode(symbol, context, SymbolFlags.Value); } - else if (context.visitedSymbols && context.visitedSymbols.has(id)) { + else if (context.visitedTypes && context.visitedTypes.has(typeId)) { // If type is an anonymous type literal in a type alias declaration, use type alias name const typeAlias = getTypeAliasForTypeLiteral(type); if (typeAlias) { @@ -3455,19 +3457,35 @@ namespace ts { } else { context.approximateLength += 3; + if (!(context.flags & NodeBuilderFlags.NoTruncation)) { + return createTypeReferenceNode(createIdentifier("..."), /*typeArguments*/ undefined); + } return createKeywordTypeNode(SyntaxKind.AnyKeyword); } } else { // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead // of types allows us to catch circular references to instantiations of the same anonymous type - if (!context.visitedSymbols) { - context.visitedSymbols = createMap(); + if (!context.visitedTypes) { + context.visitedTypes = createMap(); + } + if (!context.symbolDepth) { + context.symbolDepth = createMap(); } - context.visitedSymbols.set(id, true); + const depth = context.symbolDepth.get(id) || 0; + if (depth > 10) { + context.approximateLength += 3; + if (!(context.flags & NodeBuilderFlags.NoTruncation)) { + return createTypeReferenceNode(createIdentifier("..."), /*typeArguments*/ undefined); + } + return createKeywordTypeNode(SyntaxKind.AnyKeyword); + } + context.symbolDepth.set(id, depth + 1); + context.visitedTypes.set(typeId, true); const result = createTypeNodeFromObjectType(type); - context.visitedSymbols.delete(id); + context.visitedTypes.delete(typeId); + context.symbolDepth.set(id, depth); return result; } } @@ -3484,7 +3502,7 @@ namespace ts { declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock)); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions - return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || (context.visitedSymbols && context.visitedSymbols.has(id))) && // it is type of the symbol uses itself recursively + return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || (context.visitedTypes && context.visitedTypes.has(typeId))) && // it is type of the symbol uses itself recursively (!(context.flags & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration!)); // TODO: GH#18217 // And the build is going to succeed without visibility error or there is no structural fallback allowed } } @@ -4308,7 +4326,8 @@ namespace ts { // State encounteredError: boolean; - visitedSymbols: Map | undefined; + visitedTypes: Map | undefined; + symbolDepth: Map | undefined; inferTypeParameters: TypeParameter[] | undefined; approximateLength: number; truncating?: boolean; diff --git a/tests/baselines/reference/cyclicGenericTypeInstantiation.types b/tests/baselines/reference/cyclicGenericTypeInstantiation.types index 6925d659faf3e..473d877cfbd93 100644 --- a/tests/baselines/reference/cyclicGenericTypeInstantiation.types +++ b/tests/baselines/reference/cyclicGenericTypeInstantiation.types @@ -1,58 +1,58 @@ === tests/cases/compiler/cyclicGenericTypeInstantiation.ts === function foo() { ->foo : () => { y2: any; } +>foo : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var z = foo(); ->z : { y2: any; } ->foo() : { y2: any; } ->foo : () => { y2: any; } ->y : { y2: any; } +>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>foo() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>foo : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var y: { ->y : { y2: any; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } y2: typeof z ->y2 : { y2: any; } ->z : { y2: any; } +>y2 : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } }; return y; ->y : { y2: any; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } } function bar() { ->bar : () => { y2: any; } +>bar : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var z = bar(); ->z : { y2: any; } ->bar() : { y2: any; } ->bar : () => { y2: any; } ->y : { y2: any; } +>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>bar() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>bar : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var y: { ->y : { y2: any; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } y2: typeof z; ->y2 : { y2: any; } ->z : { y2: any; } +>y2 : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } } return y; ->y : { y2: any; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } } var a = foo(); ->a : { y2: any; } ->foo() : { y2: any; } ->foo : () => { y2: any; } +>a : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>foo() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>foo : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var b = bar(); ->b : { y2: any; } ->bar() : { y2: any; } ->bar : () => { y2: any; } +>b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>bar() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>bar : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } a = b; ->a = b : { y2: any; } ->a : { y2: any; } ->b : { y2: any; } +>a = b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>a : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } diff --git a/tests/baselines/reference/cyclicGenericTypeInstantiationInference.types b/tests/baselines/reference/cyclicGenericTypeInstantiationInference.types index fe4d54cf41756..e7597e9055ebc 100644 --- a/tests/baselines/reference/cyclicGenericTypeInstantiationInference.types +++ b/tests/baselines/reference/cyclicGenericTypeInstantiationInference.types @@ -1,63 +1,63 @@ === tests/cases/compiler/cyclicGenericTypeInstantiationInference.ts === function foo() { ->foo : () => { y2: any; } +>foo : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var z = foo(); ->z : { y2: any; } ->foo() : { y2: any; } ->foo : () => { y2: any; } ->y : { y2: any; } +>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>foo() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>foo : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var y: { ->y : { y2: any; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } y2: typeof z ->y2 : { y2: any; } ->z : { y2: any; } +>y2 : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } }; return y; ->y : { y2: any; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } } function bar() { ->bar : () => { y2: any; } +>bar : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var z = bar(); ->z : { y2: any; } ->bar() : { y2: any; } ->bar : () => { y2: any; } ->y : { y2: any; } +>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>bar() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>bar : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var y: { ->y : { y2: any; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } y2: typeof z; ->y2 : { y2: any; } ->z : { y2: any; } +>y2 : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } } return y; ->y : { y2: any; } +>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } } var a = foo(); ->a : { y2: any; } ->foo() : { y2: any; } ->foo : () => { y2: any; } +>a : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>foo() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>foo : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } var b = bar(); ->b : { y2: any; } ->bar() : { y2: any; } ->bar : () => { y2: any; } +>b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>bar() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>bar : () => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } function test(x: typeof a): void { } ->test : (x: { y2: any; }) => void ->x : { y2: any; } ->a : { y2: any; } +>test : (x: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }) => void +>x : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } +>a : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } test(b); >test(b) : void ->test : (x: { y2: any; }) => void ->b : { y2: any; } +>test : (x: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }) => void +>b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; } diff --git a/tests/baselines/reference/genericCallWithObjectLiteralArgs.types b/tests/baselines/reference/genericCallWithObjectLiteralArgs.types index 94a2111489646..e19a6b327c614 100644 --- a/tests/baselines/reference/genericCallWithObjectLiteralArgs.types +++ b/tests/baselines/reference/genericCallWithObjectLiteralArgs.types @@ -30,8 +30,8 @@ var r2 = foo({ bar: 1, baz: 1 }); // T = number >1 : 1 var r3 = foo({ bar: foo, baz: foo }); // T = typeof foo ->r3 : { bar: (x: any) => any; baz: (x: any) => any; } ->foo({ bar: foo, baz: foo }) : { bar: (x: any) => any; baz: (x: any) => any; } +>r3 : { bar: (x: { bar: T; baz: T; }) => { bar: T; baz: T; }; baz: (x: { bar: T; baz: T; }) => { bar: T; baz: T; }; } +>foo({ bar: foo, baz: foo }) : { bar: (x: { bar: T; baz: T; }) => { bar: T; baz: T; }; baz: (x: { bar: T; baz: T; }) => { bar: T; baz: T; }; } >foo : (x: { bar: T; baz: T; }) => { bar: T; baz: T; } >{ bar: foo, baz: foo } : { bar: (x: { bar: T; baz: T; }) => { bar: T; baz: T; }; baz: (x: { bar: T; baz: T; }) => { bar: T; baz: T; }; } >bar : (x: { bar: T; baz: T; }) => { bar: T; baz: T; } diff --git a/tests/baselines/reference/limitDeepInstantiations.types b/tests/baselines/reference/limitDeepInstantiations.types index bce090db14b26..f52ea1497cad8 100644 --- a/tests/baselines/reference/limitDeepInstantiations.types +++ b/tests/baselines/reference/limitDeepInstantiations.types @@ -2,8 +2,8 @@ // Repro from #14837 type Foo = { "true": Foo> }[T]; ->Foo : { "true": any[T]; }[T] ->"true" : { "true": any[T]; }[T] +>Foo : { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": any[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T] +>"true" : { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": any[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T] let f1: Foo<"true", {}>; >f1 : any diff --git a/tests/baselines/reference/moduleExportPropertyAssignmentDefault.types b/tests/baselines/reference/moduleExportPropertyAssignmentDefault.types index 05d88c53cb064..a2f69a87f280b 100644 --- a/tests/baselines/reference/moduleExportPropertyAssignmentDefault.types +++ b/tests/baselines/reference/moduleExportPropertyAssignmentDefault.types @@ -4,18 +4,18 @@ var axios = {} >{} : {} module.exports = axios // both assignments should be ok ->module.exports = axios : { default: any; } ->module.exports : { default: any; } ->module : { "tests/cases/conformance/salsa/axios": { default: any; }; } ->exports : { default: any; } +>module.exports = axios : { default: { default: any; }; } +>module.exports : { default: { default: any; }; } +>module : { "tests/cases/conformance/salsa/axios": { default: { default: any; }; }; } +>exports : { default: { default: any; }; } >axios : { default: { default: any; }; } module.exports.default = axios >module.exports.default = axios : { default: { default: any; }; } >module.exports.default : { default: any; } ->module.exports : { default: any; } ->module : { "tests/cases/conformance/salsa/axios": { default: any; }; } ->exports : { default: any; } +>module.exports : { default: { default: any; }; } +>module : { "tests/cases/conformance/salsa/axios": { default: { default: any; }; }; } +>exports : { default: { default: any; }; } >default : { default: any; } >axios : { default: { default: any; }; } diff --git a/tests/baselines/reference/recursiveLetConst.types b/tests/baselines/reference/recursiveLetConst.types index 7e4db6687aab1..90b0d7baab1f7 100644 --- a/tests/baselines/reference/recursiveLetConst.types +++ b/tests/baselines/reference/recursiveLetConst.types @@ -63,7 +63,7 @@ let z1 = function () { return z1; } let z2 = { f() { return z2;}} >z2 : { f(): any; } ->{ f() { return z2;}} : { f(): any; } +>{ f() { return z2;}} : { f(): { f(): any; }; } >f : () => { f(): any; } >z2 : { f(): any; } diff --git a/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts b/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts index 15ff0aca5cbbd..ddb98711629ea 100644 --- a/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts +++ b/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts @@ -9,4 +9,4 @@ /////// ////foo(); -verify.singleReferenceGroup("(local function) foo(a?: void, b?: () => (a?: void, b?: any) => void): void"); +verify.singleReferenceGroup("(local function) foo(a?: void, b?: () => (a?: void, b?: ...) => void): void"); diff --git a/tests/cases/fourslash/quickInforForSucessiveInferencesIsNotAny.ts b/tests/cases/fourslash/quickInforForSucessiveInferencesIsNotAny.ts new file mode 100644 index 0000000000000..367b4960abd94 --- /dev/null +++ b/tests/cases/fourslash/quickInforForSucessiveInferencesIsNotAny.ts @@ -0,0 +1,18 @@ +/// + +////declare function schema (value : T) : {field : T}; +//// +////declare const b: boolean; +////const obj/*1*/ = schema(b); +////const actualTypeOfNested/*2*/ = schema(obj); + +verify.quickInfos({ + 1: `const obj: { + field: boolean; +}`, + 2: `const actualTypeOfNested: { + field: { + field: boolean; + }; +}` +});