Search code examples
typescript

Transform type into object literal


I'd like the following:

type OutlinedButtonProps = {
  fill: 'outlined';
  color?: 'primary' | 'danger' | 'neutral';
};

To be transformed into:

const outlinedButtonProps = {
  fill: ['outlined'],
  color: ['primary', 'danger', 'neutral']
};

Is this possible?


Solution

  • This is impossible as asked. The TypeScript compiler completely erases the type system upon compilation to JavaScript. So the OutlinedButtonProps type alias will just be gone, and there's nothing from which to create a runtime value.

    Indeed TypeScript will almost certainly never support this sort of thing directly. It is explicitly mentioned as TypeScript Design Non-Goal #5. TypeScript does not intend to "add or rely on run-time type information in programs, or emit different code based on the results of the type system. Instead, [it] encourage[s] programming patterns that do not require run-time metadata."

    If you need something like that, you'll have to look into adding some kind of code generation build step to your project, but that's outside the scope of pure TypeScript now.


    What you can do is the reverse, and start with an array and then have TypeScript compute your type from it:

    const outlinedButtonProps = {
      fill: ['outlined'],
      color: ['primary', 'danger', 'neutral']
    } as const
    
    type BaseOutlinedButtonProps =
      { -readonly [K in keyof typeof outlinedButtonProps]:
        typeof outlinedButtonProps[K][number] };
    
    type PickPartial<T, K extends keyof T> = Partial<T> &
      Omit<T, K> extends infer U ? { [P in keyof U]: U[P] } : never
    
    type OutlinedButtonProps = PickPartial<BaseOutlinedButtonProps, "color">
    /* type OutlinedButtonProps = {
        fill: "outlined";
        color?: "primary" | "danger" | "neutral";
    } */
    

    That's not directly what was asked for in the question, but some readers might find it satisfies their use cases. I mean, at least it's possible to do it this way.

    Playground link to code