From 0e641ff33f47a8e0943d22986bec784aabf7cff7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 18 Sep 2026 15:40:22 -0700 Subject: [PATCH 01/10] Idempotent resolution of object type members --- tsc/internal/checker/checker.go | 17 ++++++++++++----- tsc/internal/checker/types.go | 3 +-- .../diagnostics/diagnosticMessages.json | 4 ++++ .../diagnostics/diagnostics_generated.go | 4 ++++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 8aec6df21d7af..cb0d6f3f95e42 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -64,6 +64,7 @@ const ( TypeSystemPropertyNameWriteType TypeSystemPropertyNameInitializerIsUndefined TypeSystemPropertyNameAliasTarget + TypeSystemPropertyNameMembers ) type TypeResolution struct { @@ -237,7 +238,6 @@ type PropertiesTypesKey struct { typeId TypeId include TypeFlags includeOrigin bool - unresolvedMembers bool } // NonExistentPropertyKey @@ -19147,6 +19147,8 @@ func (c *Checker) typeResolutionHasProperty(r *TypeResolution) bool { return c.valueSymbolLinks.Get(r.target.(*ast.Symbol)).writeType != nil case TypeSystemPropertyNameAliasTarget: return c.aliasSymbolLinks.Get(r.target.(*ast.Symbol)).aliasTarget != nil + case TypeSystemPropertyNameMembers: + return r.target.(*Type).objectFlags&ObjectFlagsMembersResolved != 0 } panic("Unhandled case in typeResolutionHasProperty") } @@ -19461,9 +19463,11 @@ func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters if !instantiated { members = maps.Clone(members) } - c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos) + if !c.pushTypeResolution(t, TypeSystemPropertyNameMembers) { + c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos) + return + } thisArgument := core.LastOrNil(typeArguments) - t.objectFlags |= ObjectFlagsUnresolvedMembers for _, baseType := range baseTypes { instantiatedBaseType := baseType if thisArgument != nil { @@ -19482,7 +19486,10 @@ func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters return findIndexInfo(indexInfos, info.keyType) == nil })) } - t.objectFlags &^= ObjectFlagsUnresolvedMembers + if !c.popTypeResolution() { + c.error(c.currentNode, diagnostics.A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type, c.TypeToString(t)) + return + } } c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos) } @@ -27113,7 +27120,7 @@ func (c *Checker) getExtractStringType(t *Type) *Type { } func (c *Checker) getLiteralTypeFromProperties(t *Type, include TypeFlags, includeOrigin bool) *Type { - key := PropertiesTypesKey{typeId: t.id, include: include, includeOrigin: includeOrigin, unresolvedMembers: t.objectFlags&ObjectFlagsUnresolvedMembers != 0} + key := PropertiesTypesKey{typeId: t.id, include: include, includeOrigin: includeOrigin} if cached, ok := c.propertiesTypes[key]; ok { return cached } diff --git a/tsc/internal/checker/types.go b/tsc/internal/checker/types.go index 1ec80b0a26f62..bd4e3e0f3657a 100644 --- a/tsc/internal/checker/types.go +++ b/tsc/internal/checker/types.go @@ -642,8 +642,7 @@ const ( // Flags that require TypeFlags.Object and ObjectFlags.Reference ObjectFlagsIdenticalBaseTypeCalculated = 1 << 27 // has had `getSingleBaseForNonAugmentingSubtype` invoked on it already ObjectFlagsIdenticalBaseTypeExists = 1 << 28 // has a defined cachedEquivalentBaseType member - ObjectFlagsUnresolvedMembers = 1 << 29 // Member resolution in process - ObjectFlagsFromTypeNode = 1 << 30 // Originates in resolution of AST type node + ObjectFlagsFromTypeNode = 1 << 29 // Originates in resolution of AST type node // Flags that require TypeFlags.UnionOrIntersection or TypeFlags.Substitution ObjectFlagsIsGenericTypeComputed = 1 << 22 // IsGenericObjectType flag has been computed ObjectFlagsIsGenericObjectType = 1 << 23 // Union or intersection contains generic object type diff --git a/tsc/internal/diagnostics/diagnosticMessages.json b/tsc/internal/diagnostics/diagnosticMessages.json index 8fef6d37ff389..78ffa93fa2891 100644 --- a/tsc/internal/diagnostics/diagnosticMessages.json +++ b/tsc/internal/diagnostics/diagnosticMessages.json @@ -4772,6 +4772,10 @@ "category": "Error", "code": 5113 }, + "A base type of '{0}' has type arguments that circularly reference members of the type.": { + "category": "Error", + "code": 5114 + }, "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", diff --git a/tsc/internal/diagnostics/diagnostics_generated.go b/tsc/internal/diagnostics/diagnostics_generated.go index abab44d7a6fab..4c1b7e4e9b699 100644 --- a/tsc/internal/diagnostics/diagnostics_generated.go +++ b/tsc/internal/diagnostics/diagnostics_generated.go @@ -2388,6 +2388,8 @@ var X_tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_ var X_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here = &Message{code: 5113, category: CategoryError, key: "_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here_5113", text: "'{0}' is only assignable to the non-distributed '{1}', but '{1}' has been distributed here."} +var A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type = &Message{code: 5114, category: CategoryError, key: "A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type_5114", text: "A base type of '{0}' has type arguments that circularly reference members of the type."} + var Generates_a_sourcemap_for_each_corresponding_d_ts_file = &Message{code: 6000, category: CategoryMessage, key: "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", text: "Generates a sourcemap for each corresponding '.d.ts' file."} var Concatenate_and_emit_output_to_single_file = &Message{code: 6001, category: CategoryMessage, key: "Concatenate_and_emit_output_to_single_file_6001", text: "Concatenate and emit output to single file."} @@ -6816,6 +6818,8 @@ func keyToMessage(key Key) *Message { return X_tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_commandline_Use_ignoreConfig_to_skip_this_error case "_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here_5113": return X_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here + case "A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type_5114": + return A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type case "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000": return Generates_a_sourcemap_for_each_corresponding_d_ts_file case "Concatenate_and_emit_output_to_single_file_6001": From adb67845a3b091637271adac32fc03954c83e5b5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 18 Sep 2026 15:42:55 -0700 Subject: [PATCH 02/10] Accept new baselines --- ...enericExtendingClassDoubleLayer.errors.txt | 13 +- .../keyofUnresolvedBaseMembers.errors.txt | 41 ++++ .../mutuallyRecursiveInference.errors.txt | 8 +- .../recursiveTypeInference.errors.txt | 186 ++++++++++++++++++ .../compiler/recursiveTypeInference.types | 12 +- 5 files changed, 252 insertions(+), 8 deletions(-) create mode 100644 tsc/testdata/baselines/reference/compiler/keyofUnresolvedBaseMembers.errors.txt create mode 100644 tsc/testdata/baselines/reference/compiler/recursiveTypeInference.errors.txt diff --git a/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt b/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt index fcd3ce0adb0da..fb19b6514e1a3 100644 --- a/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt @@ -1,8 +1,12 @@ keyofGenericExtendingClassDoubleLayer.ts(2,12): error TS2564: Property 'createdAt' has no initializer and is not definitely assigned in the constructor. +keyofGenericExtendingClassDoubleLayer.ts(9,7): error TS5114: A base type of 'AutoModel' has type arguments that circularly reference members of the type. +keyofGenericExtendingClassDoubleLayer.ts(9,7): error TS5114: A base type of 'PersonModel' has type arguments that circularly reference members of the type. keyofGenericExtendingClassDoubleLayer.ts(10,12): error TS2564: Property 'age' has no initializer and is not definitely assigned in the constructor. +keyofGenericExtendingClassDoubleLayer.ts(13,13): error TS2322: Type 'string' is not assignable to type 'keyof this'. + Type '"createdAt"' is not assignable to type '"age" | "toJson"'. -==== keyofGenericExtendingClassDoubleLayer.ts (2 errors) ==== +==== keyofGenericExtendingClassDoubleLayer.ts (5 errors) ==== class Model { public createdAt: Date; ~~~~~~~~~ @@ -14,12 +18,19 @@ keyofGenericExtendingClassDoubleLayer.ts(10,12): error TS2564: Property 'age' ha class AutoModel extends Model> {} class PersonModel extends AutoModel { + ~~~~~~~~~~~ +!!! error TS5114: A base type of 'AutoModel' has type arguments that circularly reference members of the type. + ~~~~~~~~~~~ +!!! error TS5114: A base type of 'PersonModel' has type arguments that circularly reference members of the type. public age: number; ~~~ !!! error TS2564: Property 'age' has no initializer and is not definitely assigned in the constructor. toJson() { let x: keyof this = 'createdAt'; + ~ +!!! error TS2322: Type 'string' is not assignable to type 'keyof this'. +!!! error TS2322: Type '"createdAt"' is not assignable to type '"age" | "toJson"'. } } \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/keyofUnresolvedBaseMembers.errors.txt b/tsc/testdata/baselines/reference/compiler/keyofUnresolvedBaseMembers.errors.txt new file mode 100644 index 0000000000000..0d9d6d498b3d5 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/keyofUnresolvedBaseMembers.errors.txt @@ -0,0 +1,41 @@ +keyofUnresolvedBaseMembers.ts(12,36): error TS2313: Type parameter 'K' has a circular constraint. +keyofUnresolvedBaseMembers.ts(17,7): error TS5114: A base type of 'BaseModel<_Foo>' has type arguments that circularly reference members of the type. +keyofUnresolvedBaseMembers.ts(17,7): error TS5114: A base type of '_Foo' has type arguments that circularly reference members of the type. +keyofUnresolvedBaseMembers.ts(21,7): error TS2322: Type 'typeof _Foo' is not assignable to type 'new () => STModel'. + Type '_Foo' is missing the following properties from type 'STModel': $add, $set, data, newAttrs + + +==== keyofUnresolvedBaseMembers.ts (4 errors) ==== + // https://github.com/microsoft/TypeScript/tsc/issues/3494 + + declare class STModel { + $add: (propertyKey: string) => void; + $set: (propertyKey: keyof this) => void; + data: TAttrs; + newAttrs: TCreate; + } + + interface IBase { id: string } + + type Attrs = { [K in keyof T]: T[K] } & IBase; + ~~~~~~~ +!!! error TS2313: Type parameter 'K' has a circular constraint. +!!! related TS2751 keyofUnresolvedBaseMembers.ts:17:7: Circularity originates in type at this location. + type CreateAttrs = Partial>; + + abstract class BaseModel extends STModel, CreateAttrs> {} + + class _Foo extends BaseModel<_Foo> { + ~~~~ +!!! error TS5114: A base type of 'BaseModel<_Foo>' has type arguments that circularly reference members of the type. + ~~~~ +!!! error TS5114: A base type of '_Foo' has type arguments that circularly reference members of the type. + declare name: string; + } + + const ctor: new () => STModel = _Foo; + ~~~~ +!!! error TS2322: Type 'typeof _Foo' is not assignable to type 'new () => STModel'. +!!! error TS2322: Type '_Foo' is missing the following properties from type 'STModel': $add, $set, data, newAttrs + console.log(ctor); + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt b/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt index 5b6b3f6f75a76..819ce6111b335 100644 --- a/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt @@ -1,9 +1,11 @@ mutuallyRecursiveInference.ts(2,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. mutuallyRecursiveInference.ts(9,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. mutuallyRecursiveInference.ts(10,5): error TS2564: Property 'b' has no initializer and is not definitely assigned in the constructor. +mutuallyRecursiveInference.ts(12,9): error TS5114: A base type of 'L' has type arguments that circularly reference members of the type. +mutuallyRecursiveInference.ts(12,9): error TS5114: A base type of 'X' has type arguments that circularly reference members of the type. -==== mutuallyRecursiveInference.ts (3 errors) ==== +==== mutuallyRecursiveInference.ts (5 errors) ==== class T { a: A; ~ @@ -22,6 +24,10 @@ mutuallyRecursiveInference.ts(10,5): error TS2564: Property 'b' has no initializ !!! error TS2564: Property 'b' has no initializer and is not definitely assigned in the constructor. m2() { this.a + ~~~~~~ +!!! error TS5114: A base type of 'L' has type arguments that circularly reference members of the type. + ~~~~~~ +!!! error TS5114: A base type of 'X' has type arguments that circularly reference members of the type. } } \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.errors.txt b/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.errors.txt new file mode 100644 index 0000000000000..3ee680372a70a --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.errors.txt @@ -0,0 +1,186 @@ +recursiveTypeInference.ts(99,18): error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' has type arguments that circularly reference members of the type. +recursiveTypeInference.ts(101,7): error TS2322: Type '$ZodArray<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' is not assignable to type '$ZodType>'. + Types of property '_zod' are incompatible. + Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input +recursiveTypeInference.ts(128,12): error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' has type arguments that circularly reference members of the type. +recursiveTypeInference.ts(128,12): error TS5114: A base type of '$ZodNullableInternals<$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>>' has type arguments that circularly reference members of the type. +recursiveTypeInference.ts(128,23): error TS2345: Argument of type '$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' is not assignable to parameter of type '$ZodType>'. + Types of property '_zod' are incompatible. + Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input +recursiveTypeInference.ts(137,12): error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' has type arguments that circularly reference members of the type. +recursiveTypeInference.ts(137,12): error TS5114: A base type of '$ZodOptionalInternals<$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>>' has type arguments that circularly reference members of the type. +recursiveTypeInference.ts(137,23): error TS2345: Argument of type '$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' is not assignable to parameter of type '$ZodType>'. + Types of property '_zod' are incompatible. + Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input + + +==== recursiveTypeInference.ts (8 errors) ==== + // Adaptation of examples from https://github.com/microsoft/TypeScript/issues/64192. + + export interface _$ZodTypeInternals { + def: unknown; + optin?: "optional" | undefined; + optout?: "optional" | undefined; + } + + export interface $ZodTypeInternals extends _$ZodTypeInternals { + output: O; + input: I; + } + + export type output = T["_zod"]["output"]; + export type input = T["_zod"]["input"]; + + export interface $ZodType = $ZodTypeInternals> { + _zod: Internals; + } + + // ---- string ---- + export interface $ZodStringInternals extends $ZodTypeInternals { + def: { type: "string" }; + } + export interface $ZodString extends $ZodType { + _zod: $ZodStringInternals; + } + declare function string(): $ZodString; + + // ---- array ---- + export interface $ZodArrayInternals extends $ZodTypeInternals[], input[]> { + def: { type: "array"; element: T }; + } + export interface $ZodArray extends $ZodType { + _zod: $ZodArrayInternals; + } + declare function array(element: T): $ZodArray; + + // ---- optional ---- + export interface $ZodOptionalInternals + extends $ZodTypeInternals | undefined, input | undefined> { + def: { type: "optional"; innerType: T }; + optin: "optional"; + optout: "optional"; + } + export interface $ZodOptional extends $ZodType { + _zod: $ZodOptionalInternals; + } + declare function optional(inner: T): $ZodOptional; + + // ---- nullable ---- + export interface $ZodNullableInternals + extends $ZodTypeInternals | null, input | null> { + def: { type: "nullable"; innerType: T }; + } + export interface $ZodNullable extends $ZodType { + _zod: $ZodNullableInternals; + } + declare function nullable(inner: T): $ZodNullable; + + // ---- object ---- + type OptionalOutSchema = { _zod: { optout: "optional" } }; + type OptionalInSchema = { _zod: { optin: "optional" } }; + + export type $ZodShape = Readonly<{ [k: string]: $ZodType }>; + + export type Prettify = { [K in keyof T]: T[K] } & {}; + + export type $InferObjectOutput = Prettify< + { + -readonly [k in keyof T as T[k] extends OptionalOutSchema ? never : k]: T[k]["_zod"]["output"]; + } & { + -readonly [k in keyof T as T[k] extends OptionalOutSchema ? k : never]?: T[k]["_zod"]["output"]; + } + >; + export type $InferObjectInput = Prettify< + { + -readonly [k in keyof T as T[k] extends OptionalInSchema ? never : k]: T[k]["_zod"]["input"]; + } & { + -readonly [k in keyof T as T[k] extends OptionalInSchema ? k : never]?: T[k]["_zod"]["input"]; + } + >; + + export interface $ZodObjectInternals extends $ZodTypeInternals { + def: { type: "object"; shape: Shape }; + output: $InferObjectOutput; + input: $InferObjectInput; + } + export interface $ZodObject extends $ZodType { + _zod: $ZodObjectInternals; + } + declare function object(shape: T): $ZodObject; + + export const z = { string, array, object, optional, nullable }; + + /* ======================= RECURSION TESTS ======================= */ + + // (1) plain self reference through array + const Category = z.object({ + ~~~~~~~~~~ + name: z.string(), + ~~~~~~~~~~~~~~~~~~~ + get subcategories() { + ~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~ +!!! error TS2322: Type '$ZodArray<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' is not assignable to type '$ZodType>'. +!!! error TS2322: Types of property '_zod' are incompatible. +!!! error TS2322: Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input + return z.array(Category); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }, + ~~~~ + }); + ~~ +!!! error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' has type arguments that circularly reference members of the type. + type Category = output; + export const _c: Category = { name: "a", subcategories: [{ name: "b", subcategories: [] }] }; + + // (2) mutual recursion + const User = z.object({ + email: z.string(), + get posts() { + return z.array(Post); + }, + }); + const Post = z.object({ + title: z.string(), + get author() { + return User; + }, + }); + export type UserT = output; + export const _u: UserT = { email: "e", posts: [{ title: "t", author: { email: "e2", posts: [] } }] }; + + // (3) nested function calls + const Activity = z.object({ + name: z.string(), + get subactivities() { + return z.nullable(z.array(Activity)); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' has type arguments that circularly reference members of the type. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS5114: A base type of '$ZodNullableInternals<$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>>' has type arguments that circularly reference members of the type. + ~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' is not assignable to parameter of type '$ZodType>'. +!!! error TS2345: Types of property '_zod' are incompatible. +!!! error TS2345: Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input + }, + }); + export type ActivityT = output; + + // (4) reference through a separately-declared const + const Node1 = z.object({ + name: z.string(), + get children() { + return z.optional(NodeArray); + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' has type arguments that circularly reference members of the type. + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS5114: A base type of '$ZodOptionalInternals<$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>>' has type arguments that circularly reference members of the type. + ~~~~~~~~~ +!!! error TS2345: Argument of type '$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' is not assignable to parameter of type '$ZodType>'. +!!! error TS2345: Types of property '_zod' are incompatible. +!!! error TS2345: Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input + }, + }); + const NodeArray = z.array(Node1); + export type Node1T = output; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types b/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types index 914b8260ed821..f96cc6a6d3c32 100644 --- a/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types +++ b/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types @@ -168,7 +168,7 @@ export const z = { string, array, object, optional, nullable }; // (1) plain self reference through array const Category = z.object({ >Category : $ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }> ->z.object({ name: z.string(), get subcategories() { return z.array(Category); },}) : $ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }> +>z.object({ name: z.string(), get subcategories() { return z.array(Category); },}) : $ZodObject>; }>> >z.object : (shape: T) => $ZodObject >z : { string: () => $ZodString; array: (element: T) => $ZodArray; object: (shape: T) => $ZodObject; optional: (inner: T) => $ZodOptional; nullable: (inner: T) => $ZodNullable; } >object : (shape: T) => $ZodObject @@ -194,11 +194,11 @@ const Category = z.object({ }, }); type Category = output; ->Category : { name: string; subcategories: any[]; } +>Category : { name: string; subcategories: unknown; } >Category : $ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }> export const _c: Category = { name: "a", subcategories: [{ name: "b", subcategories: [] }] }; ->_c : { name: string; subcategories: any[]; } +>_c : { name: string; subcategories: unknown; } >{ name: "a", subcategories: [{ name: "b", subcategories: [] }] } : { name: string; subcategories: { name: string; subcategories: never[]; }[]; } >name : string >"a" : "a" @@ -302,7 +302,7 @@ const Activity = z.object({ >subactivities : $ZodNullable<$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>> return z.nullable(z.array(Activity)); ->z.nullable(z.array(Activity)) : $ZodNullable<$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>> +>z.nullable(z.array(Activity)) : $ZodNullable<$ZodType>> >z.nullable : (inner: T) => $ZodNullable >z : { string: () => $ZodString; array: (element: T) => $ZodArray; object: (shape: T) => $ZodObject; optional: (inner: T) => $ZodOptional; nullable: (inner: T) => $ZodNullable; } >nullable : (inner: T) => $ZodNullable @@ -338,7 +338,7 @@ const Node1 = z.object({ >children : $ZodOptional<$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>> return z.optional(NodeArray); ->z.optional(NodeArray) : $ZodOptional<$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>> +>z.optional(NodeArray) : $ZodOptional<$ZodType>> >z.optional : (inner: T) => $ZodOptional >z : { string: () => $ZodString; array: (element: T) => $ZodArray; object: (shape: T) => $ZodObject; optional: (inner: T) => $ZodOptional; nullable: (inner: T) => $ZodNullable; } >optional : (inner: T) => $ZodOptional @@ -355,6 +355,6 @@ const NodeArray = z.array(Node1); >Node1 : $ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }> export type Node1T = output; ->Node1T : { name: string; children?: unknown; } +>Node1T : { name: string; children: unknown; } >Node1 : $ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }> From 4b00dfdf732651a3b170bbeba60fde492e2d5f44 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 19 Sep 2026 16:39:13 -0700 Subject: [PATCH 03/10] Don't use type resolution stack --- tsc/internal/checker/checker.go | 8 -------- tsc/internal/diagnostics/diagnosticMessages.json | 4 ---- tsc/internal/diagnostics/diagnostics_generated.go | 4 ---- 3 files changed, 16 deletions(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index cb0d6f3f95e42..88d470c72bac5 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -19463,10 +19463,6 @@ func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters if !instantiated { members = maps.Clone(members) } - if !c.pushTypeResolution(t, TypeSystemPropertyNameMembers) { - c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos) - return - } thisArgument := core.LastOrNil(typeArguments) for _, baseType := range baseTypes { instantiatedBaseType := baseType @@ -19486,10 +19482,6 @@ func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters return findIndexInfo(indexInfos, info.keyType) == nil })) } - if !c.popTypeResolution() { - c.error(c.currentNode, diagnostics.A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type, c.TypeToString(t)) - return - } } c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos) } diff --git a/tsc/internal/diagnostics/diagnosticMessages.json b/tsc/internal/diagnostics/diagnosticMessages.json index 78ffa93fa2891..8fef6d37ff389 100644 --- a/tsc/internal/diagnostics/diagnosticMessages.json +++ b/tsc/internal/diagnostics/diagnosticMessages.json @@ -4772,10 +4772,6 @@ "category": "Error", "code": 5113 }, - "A base type of '{0}' has type arguments that circularly reference members of the type.": { - "category": "Error", - "code": 5114 - }, "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", diff --git a/tsc/internal/diagnostics/diagnostics_generated.go b/tsc/internal/diagnostics/diagnostics_generated.go index 4c1b7e4e9b699..abab44d7a6fab 100644 --- a/tsc/internal/diagnostics/diagnostics_generated.go +++ b/tsc/internal/diagnostics/diagnostics_generated.go @@ -2388,8 +2388,6 @@ var X_tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_ var X_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here = &Message{code: 5113, category: CategoryError, key: "_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here_5113", text: "'{0}' is only assignable to the non-distributed '{1}', but '{1}' has been distributed here."} -var A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type = &Message{code: 5114, category: CategoryError, key: "A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type_5114", text: "A base type of '{0}' has type arguments that circularly reference members of the type."} - var Generates_a_sourcemap_for_each_corresponding_d_ts_file = &Message{code: 6000, category: CategoryMessage, key: "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", text: "Generates a sourcemap for each corresponding '.d.ts' file."} var Concatenate_and_emit_output_to_single_file = &Message{code: 6001, category: CategoryMessage, key: "Concatenate_and_emit_output_to_single_file_6001", text: "Concatenate and emit output to single file."} @@ -6818,8 +6816,6 @@ func keyToMessage(key Key) *Message { return X_tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_commandline_Use_ignoreConfig_to_skip_this_error case "_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here_5113": return X_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here - case "A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type_5114": - return A_base_type_of_0_has_type_arguments_that_circularly_reference_members_of_the_type case "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000": return Generates_a_sourcemap_for_each_corresponding_d_ts_file case "Concatenate_and_emit_output_to_single_file_6001": From 99f0df71929d985d5bc30520338e8ce598cb078f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 19 Sep 2026 16:39:35 -0700 Subject: [PATCH 04/10] Add fourslash test --- .../fourslash/tests/noGhostErrors_test.go | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tsc/internal/fourslash/tests/noGhostErrors_test.go diff --git a/tsc/internal/fourslash/tests/noGhostErrors_test.go b/tsc/internal/fourslash/tests/noGhostErrors_test.go new file mode 100644 index 0000000000000..01a8303a8e72b --- /dev/null +++ b/tsc/internal/fourslash/tests/noGhostErrors_test.go @@ -0,0 +1,61 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/TypeScript/tsc/internal/fourslash" + "github.com/microsoft/TypeScript/tsc/internal/testutil" +) + +func TestNoGhostErrors(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = ` +interface ZodType { + optional: "true" | "false"; + output: T; +} + +interface ZodString extends ZodType { + optional: "false"; +} + +type ZodShape = Record; +type Prettify = { [K in keyof T]: T[K] } & {}; +type InferObjectType = Prettify< + { + [k in keyof Shape as Shape[k] extends { optional: "true" } + ? k + : never]?: Shape[k]["output"]; + } & { + [k in keyof Shape as Shape[k] extends { optional: "true" } + ? never + : k]: Shape[k]["output"]; + } +>; +interface ZodObject extends ZodType> { + optional: "false"; +} + +interface ZodOptional> + extends ZodType { + optional: "true"; +} + +declare function object(shape: T): ZodObject; +declare function string(): ZodString; +declare function optional>(schema: T): ZodOptional; + +const Category = object({ + name: string(), + get parent/*1*/() { + return optional(Category); + }, +}); + +export const output = Category.output;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyQuickInfoAt(t, "1", "(accessor) parent: ZodOptional>;\n}>>", "") + f.VerifyDiagnostics(t, nil) +} From 8a33e984f6d19223462367b7236015a7a345e595 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 19 Sep 2026 16:40:14 -0700 Subject: [PATCH 05/10] Accept new baselines --- ...enericExtendingClassDoubleLayer.errors.txt | 14 +- .../keyofUnresolvedBaseMembers.errors.txt | 41 ---- .../mutuallyRecursiveInference.errors.txt | 9 +- .../recursiveTypeInference.errors.txt | 186 ------------------ .../compiler/recursiveTypeInference.types | 14 +- 5 files changed, 13 insertions(+), 251 deletions(-) delete mode 100644 tsc/testdata/baselines/reference/compiler/keyofUnresolvedBaseMembers.errors.txt delete mode 100644 tsc/testdata/baselines/reference/compiler/recursiveTypeInference.errors.txt diff --git a/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt b/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt index fb19b6514e1a3..09e03b0e339b4 100644 --- a/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt @@ -1,12 +1,9 @@ keyofGenericExtendingClassDoubleLayer.ts(2,12): error TS2564: Property 'createdAt' has no initializer and is not definitely assigned in the constructor. -keyofGenericExtendingClassDoubleLayer.ts(9,7): error TS5114: A base type of 'AutoModel' has type arguments that circularly reference members of the type. -keyofGenericExtendingClassDoubleLayer.ts(9,7): error TS5114: A base type of 'PersonModel' has type arguments that circularly reference members of the type. +keyofGenericExtendingClassDoubleLayer.ts(9,7): error TS2589: Type instantiation is excessively deep and possibly infinite. keyofGenericExtendingClassDoubleLayer.ts(10,12): error TS2564: Property 'age' has no initializer and is not definitely assigned in the constructor. -keyofGenericExtendingClassDoubleLayer.ts(13,13): error TS2322: Type 'string' is not assignable to type 'keyof this'. - Type '"createdAt"' is not assignable to type '"age" | "toJson"'. -==== keyofGenericExtendingClassDoubleLayer.ts (5 errors) ==== +==== keyofGenericExtendingClassDoubleLayer.ts (3 errors) ==== class Model { public createdAt: Date; ~~~~~~~~~ @@ -19,18 +16,13 @@ keyofGenericExtendingClassDoubleLayer.ts(13,13): error TS2322: Type 'string' is class PersonModel extends AutoModel { ~~~~~~~~~~~ -!!! error TS5114: A base type of 'AutoModel' has type arguments that circularly reference members of the type. - ~~~~~~~~~~~ -!!! error TS5114: A base type of 'PersonModel' has type arguments that circularly reference members of the type. +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. public age: number; ~~~ !!! error TS2564: Property 'age' has no initializer and is not definitely assigned in the constructor. toJson() { let x: keyof this = 'createdAt'; - ~ -!!! error TS2322: Type 'string' is not assignable to type 'keyof this'. -!!! error TS2322: Type '"createdAt"' is not assignable to type '"age" | "toJson"'. } } \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/keyofUnresolvedBaseMembers.errors.txt b/tsc/testdata/baselines/reference/compiler/keyofUnresolvedBaseMembers.errors.txt deleted file mode 100644 index 0d9d6d498b3d5..0000000000000 --- a/tsc/testdata/baselines/reference/compiler/keyofUnresolvedBaseMembers.errors.txt +++ /dev/null @@ -1,41 +0,0 @@ -keyofUnresolvedBaseMembers.ts(12,36): error TS2313: Type parameter 'K' has a circular constraint. -keyofUnresolvedBaseMembers.ts(17,7): error TS5114: A base type of 'BaseModel<_Foo>' has type arguments that circularly reference members of the type. -keyofUnresolvedBaseMembers.ts(17,7): error TS5114: A base type of '_Foo' has type arguments that circularly reference members of the type. -keyofUnresolvedBaseMembers.ts(21,7): error TS2322: Type 'typeof _Foo' is not assignable to type 'new () => STModel'. - Type '_Foo' is missing the following properties from type 'STModel': $add, $set, data, newAttrs - - -==== keyofUnresolvedBaseMembers.ts (4 errors) ==== - // https://github.com/microsoft/TypeScript/tsc/issues/3494 - - declare class STModel { - $add: (propertyKey: string) => void; - $set: (propertyKey: keyof this) => void; - data: TAttrs; - newAttrs: TCreate; - } - - interface IBase { id: string } - - type Attrs = { [K in keyof T]: T[K] } & IBase; - ~~~~~~~ -!!! error TS2313: Type parameter 'K' has a circular constraint. -!!! related TS2751 keyofUnresolvedBaseMembers.ts:17:7: Circularity originates in type at this location. - type CreateAttrs = Partial>; - - abstract class BaseModel extends STModel, CreateAttrs> {} - - class _Foo extends BaseModel<_Foo> { - ~~~~ -!!! error TS5114: A base type of 'BaseModel<_Foo>' has type arguments that circularly reference members of the type. - ~~~~ -!!! error TS5114: A base type of '_Foo' has type arguments that circularly reference members of the type. - declare name: string; - } - - const ctor: new () => STModel = _Foo; - ~~~~ -!!! error TS2322: Type 'typeof _Foo' is not assignable to type 'new () => STModel'. -!!! error TS2322: Type '_Foo' is missing the following properties from type 'STModel': $add, $set, data, newAttrs - console.log(ctor); - \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt b/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt index 819ce6111b335..aae1b68a0e0e0 100644 --- a/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt @@ -1,11 +1,10 @@ mutuallyRecursiveInference.ts(2,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. mutuallyRecursiveInference.ts(9,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. mutuallyRecursiveInference.ts(10,5): error TS2564: Property 'b' has no initializer and is not definitely assigned in the constructor. -mutuallyRecursiveInference.ts(12,9): error TS5114: A base type of 'L' has type arguments that circularly reference members of the type. -mutuallyRecursiveInference.ts(12,9): error TS5114: A base type of 'X' has type arguments that circularly reference members of the type. +mutuallyRecursiveInference.ts(12,9): error TS2589: Type instantiation is excessively deep and possibly infinite. -==== mutuallyRecursiveInference.ts (5 errors) ==== +==== mutuallyRecursiveInference.ts (4 errors) ==== class T { a: A; ~ @@ -25,9 +24,7 @@ mutuallyRecursiveInference.ts(12,9): error TS5114: A base type of 'X' has type a m2() { this.a ~~~~~~ -!!! error TS5114: A base type of 'L' has type arguments that circularly reference members of the type. - ~~~~~~ -!!! error TS5114: A base type of 'X' has type arguments that circularly reference members of the type. +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. } } \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.errors.txt b/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.errors.txt deleted file mode 100644 index 3ee680372a70a..0000000000000 --- a/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.errors.txt +++ /dev/null @@ -1,186 +0,0 @@ -recursiveTypeInference.ts(99,18): error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' has type arguments that circularly reference members of the type. -recursiveTypeInference.ts(101,7): error TS2322: Type '$ZodArray<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' is not assignable to type '$ZodType>'. - Types of property '_zod' are incompatible. - Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input -recursiveTypeInference.ts(128,12): error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' has type arguments that circularly reference members of the type. -recursiveTypeInference.ts(128,12): error TS5114: A base type of '$ZodNullableInternals<$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>>' has type arguments that circularly reference members of the type. -recursiveTypeInference.ts(128,23): error TS2345: Argument of type '$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' is not assignable to parameter of type '$ZodType>'. - Types of property '_zod' are incompatible. - Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input -recursiveTypeInference.ts(137,12): error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' has type arguments that circularly reference members of the type. -recursiveTypeInference.ts(137,12): error TS5114: A base type of '$ZodOptionalInternals<$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>>' has type arguments that circularly reference members of the type. -recursiveTypeInference.ts(137,23): error TS2345: Argument of type '$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' is not assignable to parameter of type '$ZodType>'. - Types of property '_zod' are incompatible. - Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input - - -==== recursiveTypeInference.ts (8 errors) ==== - // Adaptation of examples from https://github.com/microsoft/TypeScript/issues/64192. - - export interface _$ZodTypeInternals { - def: unknown; - optin?: "optional" | undefined; - optout?: "optional" | undefined; - } - - export interface $ZodTypeInternals extends _$ZodTypeInternals { - output: O; - input: I; - } - - export type output = T["_zod"]["output"]; - export type input = T["_zod"]["input"]; - - export interface $ZodType = $ZodTypeInternals> { - _zod: Internals; - } - - // ---- string ---- - export interface $ZodStringInternals extends $ZodTypeInternals { - def: { type: "string" }; - } - export interface $ZodString extends $ZodType { - _zod: $ZodStringInternals; - } - declare function string(): $ZodString; - - // ---- array ---- - export interface $ZodArrayInternals extends $ZodTypeInternals[], input[]> { - def: { type: "array"; element: T }; - } - export interface $ZodArray extends $ZodType { - _zod: $ZodArrayInternals; - } - declare function array(element: T): $ZodArray; - - // ---- optional ---- - export interface $ZodOptionalInternals - extends $ZodTypeInternals | undefined, input | undefined> { - def: { type: "optional"; innerType: T }; - optin: "optional"; - optout: "optional"; - } - export interface $ZodOptional extends $ZodType { - _zod: $ZodOptionalInternals; - } - declare function optional(inner: T): $ZodOptional; - - // ---- nullable ---- - export interface $ZodNullableInternals - extends $ZodTypeInternals | null, input | null> { - def: { type: "nullable"; innerType: T }; - } - export interface $ZodNullable extends $ZodType { - _zod: $ZodNullableInternals; - } - declare function nullable(inner: T): $ZodNullable; - - // ---- object ---- - type OptionalOutSchema = { _zod: { optout: "optional" } }; - type OptionalInSchema = { _zod: { optin: "optional" } }; - - export type $ZodShape = Readonly<{ [k: string]: $ZodType }>; - - export type Prettify = { [K in keyof T]: T[K] } & {}; - - export type $InferObjectOutput = Prettify< - { - -readonly [k in keyof T as T[k] extends OptionalOutSchema ? never : k]: T[k]["_zod"]["output"]; - } & { - -readonly [k in keyof T as T[k] extends OptionalOutSchema ? k : never]?: T[k]["_zod"]["output"]; - } - >; - export type $InferObjectInput = Prettify< - { - -readonly [k in keyof T as T[k] extends OptionalInSchema ? never : k]: T[k]["_zod"]["input"]; - } & { - -readonly [k in keyof T as T[k] extends OptionalInSchema ? k : never]?: T[k]["_zod"]["input"]; - } - >; - - export interface $ZodObjectInternals extends $ZodTypeInternals { - def: { type: "object"; shape: Shape }; - output: $InferObjectOutput; - input: $InferObjectInput; - } - export interface $ZodObject extends $ZodType { - _zod: $ZodObjectInternals; - } - declare function object(shape: T): $ZodObject; - - export const z = { string, array, object, optional, nullable }; - - /* ======================= RECURSION TESTS ======================= */ - - // (1) plain self reference through array - const Category = z.object({ - ~~~~~~~~~~ - name: z.string(), - ~~~~~~~~~~~~~~~~~~~ - get subcategories() { - ~~~~~~~~~~~~~~~~~~~~~~~ - ~~~~~~~~~~~~~ -!!! error TS2322: Type '$ZodArray<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' is not assignable to type '$ZodType>'. -!!! error TS2322: Types of property '_zod' are incompatible. -!!! error TS2322: Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input - return z.array(Category); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - }, - ~~~~ - }); - ~~ -!!! error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }>>' has type arguments that circularly reference members of the type. - type Category = output; - export const _c: Category = { name: "a", subcategories: [{ name: "b", subcategories: [] }] }; - - // (2) mutual recursion - const User = z.object({ - email: z.string(), - get posts() { - return z.array(Post); - }, - }); - const Post = z.object({ - title: z.string(), - get author() { - return User; - }, - }); - export type UserT = output; - export const _u: UserT = { email: "e", posts: [{ title: "t", author: { email: "e2", posts: [] } }] }; - - // (3) nested function calls - const Activity = z.object({ - name: z.string(), - get subactivities() { - return z.nullable(z.array(Activity)); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' has type arguments that circularly reference members of the type. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS5114: A base type of '$ZodNullableInternals<$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>>' has type arguments that circularly reference members of the type. - ~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' is not assignable to parameter of type '$ZodType>'. -!!! error TS2345: Types of property '_zod' are incompatible. -!!! error TS2345: Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input - }, - }); - export type ActivityT = output; - - // (4) reference through a separately-declared const - const Node1 = z.object({ - name: z.string(), - get children() { - return z.optional(NodeArray); - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS5114: A base type of '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' has type arguments that circularly reference members of the type. - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS5114: A base type of '$ZodOptionalInternals<$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>>' has type arguments that circularly reference members of the type. - ~~~~~~~~~ -!!! error TS2345: Argument of type '$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' is not assignable to parameter of type '$ZodType>'. -!!! error TS2345: Types of property '_zod' are incompatible. -!!! error TS2345: Type '$ZodArrayInternals<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>' is missing the following properties from type '$ZodTypeInternals': output, input - }, - }); - const NodeArray = z.array(Node1); - export type Node1T = output; - \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types b/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types index f96cc6a6d3c32..ac57dc4d96cea 100644 --- a/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types +++ b/tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types @@ -168,7 +168,7 @@ export const z = { string, array, object, optional, nullable }; // (1) plain self reference through array const Category = z.object({ >Category : $ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }> ->z.object({ name: z.string(), get subcategories() { return z.array(Category); },}) : $ZodObject>; }>> +>z.object({ name: z.string(), get subcategories() { return z.array(Category); },}) : $ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }> >z.object : (shape: T) => $ZodObject >z : { string: () => $ZodString; array: (element: T) => $ZodArray; object: (shape: T) => $ZodObject; optional: (inner: T) => $ZodOptional; nullable: (inner: T) => $ZodNullable; } >object : (shape: T) => $ZodObject @@ -194,11 +194,11 @@ const Category = z.object({ }, }); type Category = output; ->Category : { name: string; subcategories: unknown; } +>Category : { name: string; subcategories: any[]; } >Category : $ZodObject<{ name: $ZodString; readonly subcategories: $ZodArray<$ZodObject>; }> export const _c: Category = { name: "a", subcategories: [{ name: "b", subcategories: [] }] }; ->_c : { name: string; subcategories: unknown; } +>_c : { name: string; subcategories: any[]; } >{ name: "a", subcategories: [{ name: "b", subcategories: [] }] } : { name: string; subcategories: { name: string; subcategories: never[]; }[]; } >name : string >"a" : "a" @@ -302,7 +302,7 @@ const Activity = z.object({ >subactivities : $ZodNullable<$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>> return z.nullable(z.array(Activity)); ->z.nullable(z.array(Activity)) : $ZodNullable<$ZodType>> +>z.nullable(z.array(Activity)) : $ZodNullable<$ZodArray<$ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }>>> >z.nullable : (inner: T) => $ZodNullable >z : { string: () => $ZodString; array: (element: T) => $ZodArray; object: (shape: T) => $ZodObject; optional: (inner: T) => $ZodOptional; nullable: (inner: T) => $ZodNullable; } >nullable : (inner: T) => $ZodNullable @@ -315,7 +315,7 @@ const Activity = z.object({ }, }); export type ActivityT = output; ->ActivityT : { name: string; subactivities: unknown; } +>ActivityT : { name: string; subactivities: { name: string; subactivities: any[] | null; }[] | null; } >Activity : $ZodObject<{ name: $ZodString; readonly subactivities: $ZodNullable<$ZodArray<$ZodObject>>; }> // (4) reference through a separately-declared const @@ -338,7 +338,7 @@ const Node1 = z.object({ >children : $ZodOptional<$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>> return z.optional(NodeArray); ->z.optional(NodeArray) : $ZodOptional<$ZodType>> +>z.optional(NodeArray) : $ZodOptional<$ZodArray<$ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }>>> >z.optional : (inner: T) => $ZodOptional >z : { string: () => $ZodString; array: (element: T) => $ZodArray; object: (shape: T) => $ZodObject; optional: (inner: T) => $ZodOptional; nullable: (inner: T) => $ZodNullable; } >optional : (inner: T) => $ZodOptional @@ -355,6 +355,6 @@ const NodeArray = z.array(Node1); >Node1 : $ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }> export type Node1T = output; ->Node1T : { name: string; children: unknown; } +>Node1T : { name: string; children?: { name: string; children?: any[] | undefined; }[] | undefined; } >Node1 : $ZodObject<{ name: $ZodString; readonly children: $ZodOptional<$ZodArray<$ZodObject>>; }> From 3b0239a7128cb9ae7ec80cf42102b56c8c19ef21 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 21 Sep 2026 08:07:37 -0700 Subject: [PATCH 06/10] Remove TypeSystemPropertyName member --- tsc/internal/checker/checker.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 88d470c72bac5..6da94c3ea91b4 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -64,7 +64,6 @@ const ( TypeSystemPropertyNameWriteType TypeSystemPropertyNameInitializerIsUndefined TypeSystemPropertyNameAliasTarget - TypeSystemPropertyNameMembers ) type TypeResolution struct { @@ -19147,8 +19146,6 @@ func (c *Checker) typeResolutionHasProperty(r *TypeResolution) bool { return c.valueSymbolLinks.Get(r.target.(*ast.Symbol)).writeType != nil case TypeSystemPropertyNameAliasTarget: return c.aliasSymbolLinks.Get(r.target.(*ast.Symbol)).aliasTarget != nil - case TypeSystemPropertyNameMembers: - return r.target.(*Type).objectFlags&ObjectFlagsMembersResolved != 0 } panic("Unhandled case in typeResolutionHasProperty") } From 9cb685ebb0e3f304b746cb4bed7963c9672914ca Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 21 Sep 2026 08:37:10 -0700 Subject: [PATCH 07/10] Formatting --- tsc/internal/checker/checker.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 6da94c3ea91b4..3dfec522732fd 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -234,9 +234,9 @@ type IterationTypesKey struct { // PropertiesTypesKey type PropertiesTypesKey struct { - typeId TypeId - include TypeFlags - includeOrigin bool + typeId TypeId + include TypeFlags + includeOrigin bool } // NonExistentPropertyKey From 698e180a64e37fa2d6e74b84e921e95d959d4a6c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 21 Sep 2026 10:57:16 -0700 Subject: [PATCH 08/10] Generate enums --- packages/typescript/src/enums/objectFlags.enum.ts | 3 +-- packages/typescript/src/enums/objectFlags.ts | 3 +-- tsc/internal/api/enum_values_generated.go | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/typescript/src/enums/objectFlags.enum.ts b/packages/typescript/src/enums/objectFlags.enum.ts index 63ed4e4d3c93f..d6bf418f148ff 100644 --- a/packages/typescript/src/enums/objectFlags.enum.ts +++ b/packages/typescript/src/enums/objectFlags.enum.ts @@ -36,8 +36,7 @@ export enum ObjectFlags { IsClassInstanceClone = 1 << 26, IdenticalBaseTypeCalculated = 1 << 27, IdenticalBaseTypeExists = 1 << 28, - UnresolvedMembers = 1 << 29, - FromTypeNode = 1 << 30, + FromTypeNode = 1 << 29, IsGenericTypeComputed = 1 << 22, IsGenericObjectType = 1 << 23, IsGenericIndexType = 1 << 24, diff --git a/packages/typescript/src/enums/objectFlags.ts b/packages/typescript/src/enums/objectFlags.ts index 1c17a70d5f797..71d0b8b008110 100644 --- a/packages/typescript/src/enums/objectFlags.ts +++ b/packages/typescript/src/enums/objectFlags.ts @@ -36,8 +36,7 @@ export var ObjectFlags: any; ObjectFlags[ObjectFlags["IsClassInstanceClone"] = 67108864] = "IsClassInstanceClone"; ObjectFlags[ObjectFlags["IdenticalBaseTypeCalculated"] = 134217728] = "IdenticalBaseTypeCalculated"; ObjectFlags[ObjectFlags["IdenticalBaseTypeExists"] = 268435456] = "IdenticalBaseTypeExists"; - ObjectFlags[ObjectFlags["UnresolvedMembers"] = 536870912] = "UnresolvedMembers"; - ObjectFlags[ObjectFlags["FromTypeNode"] = 1073741824] = "FromTypeNode"; + ObjectFlags[ObjectFlags["FromTypeNode"] = 536870912] = "FromTypeNode"; ObjectFlags[ObjectFlags["IsGenericTypeComputed"] = 4194304] = "IsGenericTypeComputed"; ObjectFlags[ObjectFlags["IsGenericObjectType"] = 8388608] = "IsGenericObjectType"; ObjectFlags[ObjectFlags["IsGenericIndexType"] = 16777216] = "IsGenericIndexType"; diff --git a/tsc/internal/api/enum_values_generated.go b/tsc/internal/api/enum_values_generated.go index 678051b687573..3859fabba4411 100644 --- a/tsc/internal/api/enum_values_generated.go +++ b/tsc/internal/api/enum_values_generated.go @@ -237,7 +237,6 @@ func main() { "IsClassInstanceClone": toInt32(checker.ObjectFlagsIsClassInstanceClone), "IdenticalBaseTypeCalculated": toInt32(checker.ObjectFlagsIdenticalBaseTypeCalculated), "IdenticalBaseTypeExists": toInt32(checker.ObjectFlagsIdenticalBaseTypeExists), - "UnresolvedMembers": toInt32(checker.ObjectFlagsUnresolvedMembers), "FromTypeNode": toInt32(checker.ObjectFlagsFromTypeNode), "IsGenericTypeComputed": toInt32(checker.ObjectFlagsIsGenericTypeComputed), "IsGenericObjectType": toInt32(checker.ObjectFlagsIsGenericObjectType), From b81c37d45e925b090e4776c9f77f1e5efdf68828 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 22 Sep 2026 13:31:36 -0700 Subject: [PATCH 09/10] Improve inifite type instantiation diagnostics --- tsc/internal/checker/checker.go | 45 +++++++++++++++---- tsc/internal/checker/utilities.go | 4 ++ .../diagnostics/diagnosticMessages.json | 8 ++++ .../diagnostics/diagnostics_generated.go | 8 ++++ 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 3dfec522732fd..37765dd836ea8 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -595,7 +595,7 @@ type Checker struct { SignatureCount uint32 TotalInstantiationCount uint32 instantiationCount uint32 - instantiationDepth uint32 + instantiationStack []*Type conditionalConstraintDepth uint32 inlineLevel int serializationLevel int @@ -4719,7 +4719,7 @@ basePropertyCheck: c.error(errorNode, diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2, memberInfo.typeName, missedProperty, memberInfo.baseTypeName) } case len(memberInfo.missedProperties) > 5: - missedProperties := strings.Join(core.Map(memberInfo.missedProperties[:4], func(prop string) string { return "'" + prop + "'" }), ", ") + missedProperties := quotedAndCommaSeparated(memberInfo.missedProperties[:4]) remainingMissedProperties := len(memberInfo.missedProperties) - 4 if ast.IsClassExpression(errorNode) { c.error(errorNode, diagnostics.Non_abstract_class_expression_is_missing_implementations_for_the_following_members_of_0_Colon_1_and_2_more, memberInfo.baseTypeName, missedProperties, remainingMissedProperties) @@ -4727,7 +4727,7 @@ basePropertyCheck: c.error(errorNode, diagnostics.Non_abstract_class_0_is_missing_implementations_for_the_following_members_of_1_Colon_2_and_3_more, memberInfo.typeName, memberInfo.baseTypeName, missedProperties, remainingMissedProperties) } default: - missedProperties := strings.Join(core.Map(memberInfo.missedProperties, func(prop string) string { return "'" + prop + "'" }), ", ") + missedProperties := quotedAndCommaSeparated(memberInfo.missedProperties) if ast.IsClassExpression(errorNode) { c.error(errorNode, diagnostics.Non_abstract_class_expression_is_missing_implementations_for_the_following_members_of_0_Colon_1, memberInfo.baseTypeName, missedProperties) } else { @@ -22457,14 +22457,22 @@ func (c *Checker) instantiateTypeWithAlias(t *Type, m *TypeMapper, alias *TypeAl if t == nil || m == nil || !(c.couldContainTypeVariables(t) || (t.alias != nil && len(t.alias.typeArguments) > 0 && core.Some(t.alias.typeArguments, c.couldContainTypeVariables))) { return t } - if c.instantiationDepth == 100 || c.instantiationCount >= 5_000_000 { + if len(c.instantiationStack) == 100 || c.instantiationCount >= 5_000_000 { // We have reached 100 recursive type instantiations, or 5M type instantiations caused by the same statement // or expression. There is a very high likelihood we're dealing with a combination of infinite generic types // that perpetually generate new type identities, so we stop the recursion here by yielding the error type. if tr := c.tracer; tr != nil { - tr.Instant(tracing.PhaseCheckTypes, "instantiateType_DepthLimit", map[string]any{"typeId": t.id, "instantiationDepth": c.instantiationDepth, "instantiationCount": c.instantiationCount}) + tr.Instant(tracing.PhaseCheckTypes, "instantiateType_DepthLimit", map[string]any{"typeId": t.id, "instantiationDepth": len(c.instantiationStack), "instantiationCount": c.instantiationCount}) + } + circularTypeNames := c.getCircularTypeNames() + switch { + case len(circularTypeNames) == 1: + c.error(c.currentNode, diagnostics.Instantiations_of_type_0_appear_infinitely_circular, circularTypeNames[0]) + case len(circularTypeNames) > 1: + c.error(c.currentNode, diagnostics.Instantiations_of_the_following_types_appear_infinitely_circular_Colon_0, quotedAndCommaSeparated(circularTypeNames)) + default: + c.error(c.currentNode, diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite) } - c.error(c.currentNode, diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite) return c.errorType } index := c.findActiveMapper(m) @@ -22481,17 +22489,38 @@ func (c *Checker) instantiateTypeWithAlias(t *Type, m *TypeMapper, alias *TypeAl } c.TotalInstantiationCount++ c.instantiationCount++ - c.instantiationDepth++ + c.instantiationStack = append(c.instantiationStack, t) result := c.instantiateTypeWorker(t, m, alias) if index == -1 { c.popActiveMapper() } else { cache[key] = result } - c.instantiationDepth-- + c.instantiationStack[len(c.instantiationStack)-1] = nil + c.instantiationStack = c.instantiationStack[:len(c.instantiationStack)-1] return result } +func (c *Checker) getCircularTypeNames() []string { + typeCounts := make(map[*Type]int) + var circularTypeNames []string + for _, t := range c.instantiationStack { + typeCounts[t] = typeCounts[t] + 1 + if typeCounts[t] == 3 { + symbol := t.symbol + if t.alias != nil { + symbol = t.alias.symbol + } + if symbol != nil && len(symbol.Name) != 0 && symbol.Name[0] != '\xFE' { + if name := c.SymbolToString(symbol); !slices.Contains(circularTypeNames, name) { + circularTypeNames = append(circularTypeNames, name) + } + } + } + } + return circularTypeNames +} + func (c *Checker) pushActiveMapper(mapper *TypeMapper) { c.activeMappers = append(c.activeMappers, mapper) diff --git a/tsc/internal/checker/utilities.go b/tsc/internal/checker/utilities.go index 0a68372fcef3c..19b8416edf4b6 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -1908,3 +1908,7 @@ func GetSetAccessorValueParameter(accessor *ast.Node) *ast.Node { } return nil } + +func quotedAndCommaSeparated(items []string) string { + return strings.Join(core.Map(items, func(item string) string { return "'" + item + "'" }), ", ") +} diff --git a/tsc/internal/diagnostics/diagnosticMessages.json b/tsc/internal/diagnostics/diagnosticMessages.json index 8fef6d37ff389..ef39bc97661ff 100644 --- a/tsc/internal/diagnostics/diagnosticMessages.json +++ b/tsc/internal/diagnostics/diagnosticMessages.json @@ -4772,6 +4772,14 @@ "category": "Error", "code": 5113 }, + "Instantiations of type '{0}' appear infinitely circular.": { + "category": "Error", + "code": 5114 + }, + "Instantiations of the following types appear infinitely circular: {0}.": { + "category": "Error", + "code": 5115 + }, "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", diff --git a/tsc/internal/diagnostics/diagnostics_generated.go b/tsc/internal/diagnostics/diagnostics_generated.go index abab44d7a6fab..7a0085d1c157b 100644 --- a/tsc/internal/diagnostics/diagnostics_generated.go +++ b/tsc/internal/diagnostics/diagnostics_generated.go @@ -2388,6 +2388,10 @@ var X_tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_ var X_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here = &Message{code: 5113, category: CategoryError, key: "_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here_5113", text: "'{0}' is only assignable to the non-distributed '{1}', but '{1}' has been distributed here."} +var Instantiations_of_type_0_appear_infinitely_circular = &Message{code: 5114, category: CategoryError, key: "Instantiations_of_type_0_appear_infinitely_circular_5114", text: "Instantiations of type '{0}' appear infinitely circular."} + +var Instantiations_of_the_following_types_appear_infinitely_circular_Colon_0 = &Message{code: 5115, category: CategoryError, key: "Instantiations_of_the_following_types_appear_infinitely_circular_Colon_0_5115", text: "Instantiations of the following types appear infinitely circular: {0}."} + var Generates_a_sourcemap_for_each_corresponding_d_ts_file = &Message{code: 6000, category: CategoryMessage, key: "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", text: "Generates a sourcemap for each corresponding '.d.ts' file."} var Concatenate_and_emit_output_to_single_file = &Message{code: 6001, category: CategoryMessage, key: "Concatenate_and_emit_output_to_single_file_6001", text: "Concatenate and emit output to single file."} @@ -6816,6 +6820,10 @@ func keyToMessage(key Key) *Message { return X_tsconfig_json_is_present_but_will_not_be_loaded_if_files_are_specified_on_commandline_Use_ignoreConfig_to_skip_this_error case "_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here_5113": return X_0_is_only_assignable_to_the_non_distributed_1_but_1_has_been_distributed_here + case "Instantiations_of_type_0_appear_infinitely_circular_5114": + return Instantiations_of_type_0_appear_infinitely_circular + case "Instantiations_of_the_following_types_appear_infinitely_circular_Colon_0_5115": + return Instantiations_of_the_following_types_appear_infinitely_circular_Colon_0 case "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000": return Generates_a_sourcemap_for_each_corresponding_d_ts_file case "Concatenate_and_emit_output_to_single_file_6001": From 14fc0dc0b617dc9b3182ae37e1aa6025df9f3187 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 22 Sep 2026 13:31:47 -0700 Subject: [PATCH 10/10] Accept new baselines --- .../keyofGenericExtendingClassDoubleLayer.errors.txt | 4 ++-- .../reference/compiler/limitDeepInstantiations.errors.txt | 4 ++-- .../compiler/mutuallyRecursiveInference.errors.txt | 4 ++-- .../compiler/recursiveConditionalCrash4.errors.txt | 8 ++++---- .../reference/conformance/recursiveMappedTypes.errors.txt | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt b/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt index 09e03b0e339b4..9808b4f1f9122 100644 --- a/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/keyofGenericExtendingClassDoubleLayer.errors.txt @@ -1,5 +1,5 @@ keyofGenericExtendingClassDoubleLayer.ts(2,12): error TS2564: Property 'createdAt' has no initializer and is not definitely assigned in the constructor. -keyofGenericExtendingClassDoubleLayer.ts(9,7): error TS2589: Type instantiation is excessively deep and possibly infinite. +keyofGenericExtendingClassDoubleLayer.ts(9,7): error TS5115: Instantiations of the following types appear infinitely circular: 'Model', 'ModelAttributes', 'Exclude'. keyofGenericExtendingClassDoubleLayer.ts(10,12): error TS2564: Property 'age' has no initializer and is not definitely assigned in the constructor. @@ -16,7 +16,7 @@ keyofGenericExtendingClassDoubleLayer.ts(10,12): error TS2564: Property 'age' ha class PersonModel extends AutoModel { ~~~~~~~~~~~ -!!! error TS2589: Type instantiation is excessively deep and possibly infinite. +!!! error TS5115: Instantiations of the following types appear infinitely circular: 'Model', 'ModelAttributes', 'Exclude'. public age: number; ~~~ !!! error TS2564: Property 'age' has no initializer and is not definitely assigned in the constructor. diff --git a/tsc/testdata/baselines/reference/compiler/limitDeepInstantiations.errors.txt b/tsc/testdata/baselines/reference/compiler/limitDeepInstantiations.errors.txt index ff15ecc04b6f7..a1b033edf54ba 100644 --- a/tsc/testdata/baselines/reference/compiler/limitDeepInstantiations.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/limitDeepInstantiations.errors.txt @@ -1,4 +1,4 @@ -limitDeepInstantiations.ts(4,9): error TS2589: Type instantiation is excessively deep and possibly infinite. +limitDeepInstantiations.ts(4,9): error TS5114: Instantiations of type 'Foo' appear infinitely circular. limitDeepInstantiations.ts(5,13): error TS2344: Type '"false"' does not satisfy the constraint '"true"'. @@ -8,7 +8,7 @@ limitDeepInstantiations.ts(5,13): error TS2344: Type '"false"' does not satisfy type Foo = { "true": Foo> }[T]; let f1: Foo<"true", {}>; ~~~~~~~~~~~~~~~ -!!! error TS2589: Type instantiation is excessively deep and possibly infinite. +!!! error TS5114: Instantiations of type 'Foo' appear infinitely circular. let f2: Foo<"false", {}>; ~~~~~~~ !!! error TS2344: Type '"false"' does not satisfy the constraint '"true"'. diff --git a/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt b/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt index aae1b68a0e0e0..f267690f34e18 100644 --- a/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/mutuallyRecursiveInference.errors.txt @@ -1,7 +1,7 @@ mutuallyRecursiveInference.ts(2,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. mutuallyRecursiveInference.ts(9,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. mutuallyRecursiveInference.ts(10,5): error TS2564: Property 'b' has no initializer and is not definitely assigned in the constructor. -mutuallyRecursiveInference.ts(12,9): error TS2589: Type instantiation is excessively deep and possibly infinite. +mutuallyRecursiveInference.ts(12,9): error TS5114: Instantiations of type 'T' appear infinitely circular. ==== mutuallyRecursiveInference.ts (4 errors) ==== @@ -24,7 +24,7 @@ mutuallyRecursiveInference.ts(12,9): error TS2589: Type instantiation is excessi m2() { this.a ~~~~~~ -!!! error TS2589: Type instantiation is excessively deep and possibly infinite. +!!! error TS5114: Instantiations of type 'T' appear infinitely circular. } } \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/recursiveConditionalCrash4.errors.txt b/tsc/testdata/baselines/reference/compiler/recursiveConditionalCrash4.errors.txt index 9a55044866b75..b119a342d2de9 100644 --- a/tsc/testdata/baselines/reference/compiler/recursiveConditionalCrash4.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/recursiveConditionalCrash4.errors.txt @@ -2,9 +2,9 @@ recursiveConditionalCrash4.ts(7,16): error TS2503: Cannot find namespace 'StrIte recursiveConditionalCrash4.ts(8,5): error TS2503: Cannot find namespace 'StrIter'. recursiveConditionalCrash4.ts(9,25): error TS2304: Cannot find name 'Add'. recursiveConditionalCrash4.ts(9,37): error TS2503: Cannot find namespace 'StrIter'. -recursiveConditionalCrash4.ts(10,7): error TS2589: Type instantiation is excessively deep and possibly infinite. +recursiveConditionalCrash4.ts(10,7): error TS5114: Instantiations of type 'LengthDown' appear infinitely circular. recursiveConditionalCrash4.ts(10,31): error TS2503: Cannot find namespace 'StrIter'. -recursiveConditionalCrash4.ts(16,7): error TS2589: Type instantiation is excessively deep and possibly infinite. +recursiveConditionalCrash4.ts(16,7): error TS5114: Instantiations of type 'Foo' appear infinitely circular. ==== recursiveConditionalCrash4.ts (7 errors) ==== @@ -27,7 +27,7 @@ recursiveConditionalCrash4.ts(16,7): error TS2589: Type instantiation is excessi !!! error TS2503: Cannot find namespace 'StrIter'. : LengthDown> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2589: Type instantiation is excessively deep and possibly infinite. +!!! error TS5114: Instantiations of type 'LengthDown' appear infinitely circular. ~~~~~~~ !!! error TS2503: Cannot find namespace 'StrIter'. : Length; @@ -37,6 +37,6 @@ recursiveConditionalCrash4.ts(16,7): error TS2589: Type instantiation is excessi ? Foo : Foo ~~~~~~~~~~~~ -!!! error TS2589: Type instantiation is excessively deep and possibly infinite. +!!! error TS5114: Instantiations of type 'Foo' appear infinitely circular. : unknown; \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/recursiveMappedTypes.errors.txt b/tsc/testdata/baselines/reference/conformance/recursiveMappedTypes.errors.txt index 2d62cc6d80ce3..5d6e45f1ffa2e 100644 --- a/tsc/testdata/baselines/reference/conformance/recursiveMappedTypes.errors.txt +++ b/tsc/testdata/baselines/reference/conformance/recursiveMappedTypes.errors.txt @@ -4,7 +4,7 @@ recursiveMappedTypes.ts(7,6): error TS2456: Type alias 'Recurse1' circularly ref recursiveMappedTypes.ts(8,11): error TS2313: Type parameter 'K' has a circular constraint. recursiveMappedTypes.ts(11,6): error TS2456: Type alias 'Recurse2' circularly references itself. recursiveMappedTypes.ts(12,11): error TS2313: Type parameter 'K' has a circular constraint. -recursiveMappedTypes.ts(20,19): error TS2589: Type instantiation is excessively deep and possibly infinite. +recursiveMappedTypes.ts(20,19): error TS5114: Instantiations of type 'Circular' appear infinitely circular. recursiveMappedTypes.ts(73,5): error TS2502: '"each"' is referenced directly or indirectly in its own type annotation. recursiveMappedTypes.ts(79,1): error TS2615: Type of property '"each"' circularly references itself in mapped type '{ [P in keyof ListWidget]: undefined extends ListWidget[P] ? never : P; }'. @@ -44,7 +44,7 @@ recursiveMappedTypes.ts(79,1): error TS2615: Type of property '"each"' circularl function foo(arg: Circular): tup { ~~~~~~~~~~~~~ -!!! error TS2589: Type instantiation is excessively deep and possibly infinite. +!!! error TS5114: Instantiations of type 'Circular' appear infinitely circular. return arg; }