Search code examples
typescripttypescript-genericstypescript-utility

How to recursively replace typescript primitives with a parameterized type


type or interface could both work.

interface example {
  s: string;
  o: {
    t: string;
    arrn: number[];
    arr: {
      u: string;
    }[];
};

Would transform to

interface transformed {
  s: {
    onChange: (v: string) => void;
  };
  o: {
    t: {
      onChange: (v: string) => void;
    };
    arrn: {
      onChange: (v: number) => void;
    }[];
    arr: {
      u: {
        onChange: (v: number) => void;
      };
    }[];
};

Is this possible?

What is the direction to do something like this?


Solution

  • I think the following type satisfies what you describe:

    interface example {
      s: string;
      o: {
        t: string;
        arrn: number[];
        arr: {
          u: string;
        }[];
      };
    }
    
    type ReplacePrimitives<T> = T extends Record<any, any>
      ? { [K in keyof T]: ReplacePrimitives<T[K]> }
      : { onChange: (value: T) => void };
    
    type transformed = ReplacePrimitives<example>;
    

    It recursively replaces all primitive values with the onChange object you describe, leaving records and array structures in place.