Home  >  Q&A  >  body text

Typescript: dynamic list from array of tuples, no intersection

<p><pre class="brush:php;toolbar:false;">const intents = ["primary", "secondary", "accent", "danger"] as const; const buttonSizes = ["small", "medium", "big"] as const; type IntentType = (typeof intents)[number]; type SizeType = (typeof buttonSizes)[number]; type ButtonProps = { intent?: IntentType; size?: SizeType; } & { [K in IntentType as `${Lowercase<K>}`]?: boolean; };</pre> <p>In this code, I hope that the Vue component can receive the following properties </p> <p>or like </p> <p>now, if I write the code more statically, like:</p> <pre class="brush:php;toolbar:false;">type ButtonProps = { intent?: "primary" | "secondary" | "accent" | "danger"; size?: "small" | "medium" | "big"; primary?: boolean; secondary?: boolean; accent?: boolean; danger?: boolean; }</pre> <p>It works...but I have some other code that needs to iterate over the intent options and just have it keep repeating...</p> <p>The first example works, but for some reason VUE throws an error</p> <blockquote> <p>Internal server error: [@vue/compiler-sfc] type parameter passed to DefineProps() must be a literal type or a reference to an interface or text type. </p> </blockquote> <p>This bug appears to be known and being resolved, so it appears</p> <p>What are other ways to define ButtonProps more dynamically without using intersection? </p>
P粉163951336P粉163951336414 days ago426

reply all(1)I'll reply

  • P粉384244473

    P粉3842444732023-09-01 18:26:56

    Given that the error says "Referencing an interface or literal type", I'm assuming that defining ButtonProps as an interface extending a base type should work:

    type IntentAndSize = {
      [K in IntentType as `${Lowercase<K>}`]?: boolean;
    };
    
    interface ButtonProps extends IntentAndSize {
      intent?: IntentType;
      size?: SizeType;
    }

    Playground

    reply
    0
  • Cancelreply