typescriptgenericstypes

When are recursive type aliases allowed in Typescript?


For example:

type Foo = string | Record<string, Foo>;
type Bar = string | Array<Bar>;
interface Foo2 {
  [key: string]: string | Foo2;
}

Why are Bar and Foo2 valid types, while Foo causes Type alias 'Foo' circularly references itself.? To me these cases look quite similar.

Playground Link


Solution

  • Outlined on the PR adding recursive types, the following are allowed:

    • Instantiations of generic class and interface types (for example Array).
    • Array types (for example Foo[]).
    • Tuple types (for example [string, Foo?]).

    Foo uses a generic type alias (Record is defined using type rather than interface) Bar uses a generic interface type Foo2 uses a generic interface type

    Defining a Record equivalent as an interface does work

    interface RecordI<T> {
        [k: string]: T;
    }
    
    type Baz = string | RecordI<Baz>;
    

    And so does its inlined equivalent

    type Baz1 = string | {[key: string]: Baz1}
    

    https://github.com/microsoft/TypeScript/pull/33050#issuecomment-543365074