Recursively clone a type with non-object values as strings

Viewed 38

Say I have this type:

{
  a: number;
  b?: string;
  c: null | {
    a1: boolean;
    a2: {
      b1: number;
    }
  }
}

I want to create a type out of it that has the exact same structure, but all values (or, leaves) are replaced with strings, like this:

{
  a: string;
  b?: string;
  c: null | {
    a1: string;
    a2: {
      b1: string;
    }
  }
}

Is this even possible? Also, is it possible to create a partial type of it, in which not all keys are required (I know Partial exists).

1 Answers

You can do this with a combination of conditional and recursive types:

type Stringify<T> = { [key in keyof T]: T[key] extends object | null ? Stringify<T[key]> : string }

In use:

interface Thing {
  a: number;
  b?: string;
  c: null | {
    a1: boolean;
    a2: {
      b1: number;
    }
  }
}

const t: Stringify<Thing> = {
  a: "foo",
  b: "bar",
  c: {
    a1: "baz",
    a2: {
      b1: "qux",
    },
  },
};

Playground

Related