'How can I see the full expanded contract of a Typescript type?

If I have a collection of types that looks a bit like this, only more verbose:

type ValidValues = string | number | null
type ValidTypes = "text" | "time" | "unknown"

type Decorated = {
  name?: string | null
  type?: ValidTypes
  value?: ValidValues
  title: string
  start: number
}

type Injected = {
  extras: object
}

// overriding the types from Decorated
type Text = Decorated & Injected & {
  name: string
  type: "text"
  value: string
}

My actual code has more going on, but this shows the core idea. I don't want to have to trust myself to get the relationships between types just right. I want tooling to show me what the type definition for Text "evaluates" to, after all the type algebra.

So for the above example, I'm hoping the fields specified in Text will override the previous declarations made in the Decorated type, and the output of my hypothetical tooltip would (I hope) show me something like this:

{
  name: string
  type: "text"
  value: string
  title: string
  start: number
  extras: object
}

Is there any convenient way to get this information?



Solution 1:[1]

Just supplementing jcalz's answer with versions which work with functions.

To test, I'm adding a subobject key to Text type, and adding a function interface:

type Text = Decorated &
  Injected & {
    name: string;
    type: "text";
    value: string;
    subobject: Injected;
  };

interface SomeFunction {
  (...args: Text[]): Injected & { error: boolean };
}

The modified helpers:

export type Expand<T> = T extends (...args: infer A) => infer R
  ? (...args: Expand<A>) => Expand<R>
  : T extends infer O
  ? { [K in keyof O]: O[K] }
  : never;

export type ExpandRecursively<T> = T extends (...args: infer A) => infer R
  ? (...args: ExpandRecursively<A>) => ExpandRecursively<R>
  : T extends object
  ? T extends infer O
    ? { [K in keyof O]: ExpandRecursively<O[K]> }
    : never
  : T;

This gives:

enter image description here

expanded once type hover

recursive type hover

Objects still work fine:

enter image description here enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MHebes