How to fix Type alias 'X' circularly references itself in TypeScript
TypeScript rejects aliases that loop back to themselves in positions other than object properties or other concrete shapes, so helper aliases or generics that indirectly name the recursive type trigger TS2456 even when the runtime structure is well-founded.
Quick fix
Fixes Type alias 'X' circularly references itself
type Bar<A> = { x: A };
type Foo = Bar<Foo>; // TS2456- Spot the recursive alias
- Inline the recursive property
- Keep helper aliases less recursive
- Shuffle property order when complex intersections trigger false positives
type Bar<A> = { x: A };type Foo = Bar<Foo>; // TS2456Type alias 'X' circularly references itself
What this error means
The compiler only allows a type alias to reuse itself by assigning its own structure to a property, e.g. `type Tree = { children: Tree[] }`, because that gives the checker a finite blueprint to follow. As soon as the alias appears elsewhere on the right-hand side—the alias is passed as a generic argument, unioned directly, or referenced through another alias definition—the compiler assumes it is chasing an infinite expansion and throws "Type alias 'X' circularly references itself" (TS2456). This is a deliberate restriction that keeps type resolution finite and predictable.
Typical symptoms
- tsc reports "Type alias 'Foo' circularly references itself" (TS2456) for the alias shown in the error text.
- The IDE highlights recursive type aliases involving helper aliases, generics, or intersections even though the runtime object is finite.
- Moving the recursive block into an inline property (rather than a helper alias) makes the error disappear.
- CI builds or downstream compile checks that use tsc/tsserver fail with the message even though tests pass.
Common causes
- Defining the recursive alias through another alias or generic argument (`type Foo = Bar<Foo>`), so Foo is used outside a property position.
- Using union/intersection helpers that include the same alias on multiple branches without creating indirection via object properties.
- Property ordering differences in complex intersections or inheritance trees make the checker detect a circularity in some contexts but not others (see TypeScript issue #61443).
- Alternative toolchains (like tsgo) perform type ordering differently and can surface this error even when tsc does not (see issue #1968).
How to fix "Type alias 'X' circularly references itself"
Start with the alias named in the error message and look at everything to the right of the equals sign. The offending pattern usually looks like this:
type Bar<A> = { x: A };
type Foo = Bar<Foo>; // TS2456Here, Foo is referenced as a generic parameter, so the compiler never sees the property-level indirection and raises the circularity error.
If possible, rewrite the alias so Foo refers to itself inside an object property, which always satisfies the recursion guard:
type Foo = {
payload: Foo;
};
// or for trees
type TreeNode = {
value: string;
children: TreeNode[];
};This keeps the self-reference visible to the checker at the property level.
When you want to keep a helper alias like Bar or reuse a field definition, convert that helper into an interface or pass a concrete property that still obeys the rule:
interface Bar<A> {
x: A;
}
type Foo = Bar<{ next: Foo }>; // Allowed because Foo only appears inside propertiesInterfaces are evaluated lazily enough that TypeScript can confirm the recursion stays inside the object structure.
TypeScript's depth-first checker may see a circularity if inherited properties are ordered differently than declared ones. In the example that raised issue #61443, moving the discriminant field before recursive children made the error go away:
type FooType = { foo?: boolean };
type BaseElement<T> = FooType & {
children: CustomElement[];
type: T;
};
type CustomElement = BaseElement<'h1'>;Flip type above children if necessary or split the intersection into named interfaces to give the checker a stable path.
After refactoring, run the compiler (or targeted file check) to ensure TS2456 disappears. If you still see the message, double-check for other aliases or intersections in the same file that might carry the circularity.
Advanced notes
Checker short circuits on circularity. The FAQ explains that when typechecking walks through a cycle (e.g. it decides X must be assignable to Y if X is assignable to Y) it stops and emits a circularity error; the restriction about self references only inside properties is one way to keep that walk finite.
Ordering matters in complex trees. Issue #61443 shows how the same set of properties can trigger or avoid TS2456 simply by reordering discriminants versus recursive children. When TypeScript sees inherited members before explicit members, it may flag a circularity even if one does not exist.
Toolchain differences. The tsgo checker reported this bug for a tree type and required the team to store explicitly declared members ahead of inherited ones (#1968/#1987). Different TypeScript forks or versions might still emit TS2456 until those ordering heuristics are aligned.
Frequently asked questions
- What does "Type alias 'X' circularly references itself" mean?
- g. type Tree = { children: Tree[] }, because that gives the checker a finite blueprint to follow. As soon as the alias appears elsewhere on the right-hand side—the alias is passed as a generic argument, unioned directly, or referenced through another alias definition—the compiler assumes it is chasing an infinite expansion and throws "Type alias 'X' circularly references itself" (TS2456).
- How do I fix "Type alias 'X' circularly references itself"?
- TypeScript rejects aliases that loop back to themselves in positions other than object properties or other concrete shapes, so helper aliases or generics that indirectly name the recursive type trigger TS2456 even when the runtime structure is well-founded.
- What causes "Type alias 'X' circularly references itself"?
- Defining the recursive alias through another alias or generic argument (type Foo = Bar<Foo>), so Foo is used outside a property position. Using union/intersection helpers that include the same alias on multiple branches without creating indirection via object properties. Property ordering differences in complex intersections or inheritance trees make the checker detect a circularity in some contexts but not others (see TypeScript issue #61443).
- Is the "Type alias 'X' circularly references itself" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 🔗
- 🔗
- 🐙Github.com - 61443(GitHub)
- 🐙Github.com - 1968(GitHub)
- 🐙