Creating a dynamic list in Typescript from a tuple array without any intersections

const colors = ["red", "blue", "green", "yellow"] as const;
const buttonSizes = ["small", "medium", "large"] as const;
type ColorType = (typeof colors)[number];
type SizeType = (typeof buttonSizes)[number];

type ButtonProperties = {
  color?: ColorType;
  size?: SizeType;
} & {
  [K in ColorType as `${Lowercase<K>}`]?: boolean;
};

This code snippet showcases how a Vue component can accept different properties such as

or like

If you try to define the properties statically, like so:

type ButtonProperties = {
  color?: "red" | "blue" | "green" | "yellow";
  size?: "small" | "medium" | "large";
  red?: boolean;
  blue?: boolean;
  green?: boolean;
  yellow?: boolean;
} 

It might work... but it can become repetitive and cumbersome when iterating over color options.

The initial example works fine, although VUE may throw an error for some reason:

Internal server error: [@vue/compiler-sfc] type argument passed to defineProps() must be a literal type, or a reference to an interface or literal type.

This issue is known and is currently being addressed.

Is there a different approach to dynamically defining the ButtonProperties without using intersections?

Answer №1

When encountering the error message "reference to an interface or literal type", it is suggested that defining ButtonProps as an interface extending a base type should resolve the issue:

type IntentAndSize = {
  [K in IntentType as `${Lowercase<K>}`]?: boolean;
};

interface ButtonProps extends IntentAndSize {
  intent?: IntentType;
  size?: SizeType;
}

Playground

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing Vuejs to Modify Laravel Pivot (BelongsToMany) Table

My VueJs form is set up like this, using v-model: <select name="service_id" v-model="client.services[0].pivot.service_id"> <option v-for="service in services" v-bind:key="service.id" v-bind:value=" ...

Issue: Encountering an ObjectUnsubscribedError while using Observables in RxJS and Angular2

Currently, I am in the process of self-teaching Angular2 and realize that I need to find better resources. One issue I am facing is related to moving my data calls to a service and utilizing Reactive Subject & BehaviorSubject as recommended by a friend. Wh ...

After compilation, what happens to the AngularJS typescript files?

After utilizing AngularJS and TypeScript in Visual Studio 2015, I successfully developed a web application. Is there a way to include the .js files generated during compilation automatically into the project? Will I need to remove the .ts files bef ...

Using Linux variables in the .env file of your Vue.js project can provide a convenient way to

Using .env in a *.js file allowed me to set the BANK variable as either A_BANK or B_BANK like so: BANK=A_BANK or BANK=B_BANK However, when passing the argument as A_BANK or B_BANK like: --bank A_BANK in a shell script loop for var in $@ do if [ ${var} ...

Is it possible to eliminate the array from a property using TypeScript?

Presenting my current model: export interface SizeAndColors { size: string; color: string; }[]; In addition to the above, I also have another model where I require the SizeAndColors interface but without an array. export interface Cart { options: ...

The modal popup will be triggered by various button clicks, each displaying slightly different data within the popup

As a newcomer to Angular 4, I have encountered an interesting challenge. Currently, my code consists of two separate components for two different modals triggered by two different button clicks (Add User and Edit User). However, I now face the requiremen ...

Enhance results by combining data from user input with data retrieved asynchronously from server-side APIs

In the process of developing a web application, I am facing a challenge. There is an input field where users can enter a number and next to it, I want to display the double of that number as the output. While this can be easily achieved using client-side J ...

Disabling a Field in Angular While Preserving its Value

Hey there, late night folks! I have a quick question about Angular. I'm working with a form that includes a specific field where I set the value using patchValue, but I also need to disable this field. The issue is that after disabling it, the value i ...

Steps to reveal a div when a button is clicked within a v-for loop using VueJS

Context In my code, I am utilizing a v-for loop to display sets of buttons and corresponding input fields. Each button is supposed to trigger the display of its respective input field upon being clicked. Issue However, the problem arises when the button ...

Struggling with implementing Angular and TypeScript in this particular method

I'm dealing with a code snippet that looks like this: myMethod(data: any, layerId: string, dataSubstrings): void { someObject.on('click', function(e) { this.api.getSomething(a).subscribe((result: any) => { // ERROR CALL 1. It ...

Expanding external type declarations within Typescript

I am currently working with Typescript and the ant design library. My goal is to extend an existing interface by adding a single property. To start, I imported the original interface so you can see the folder structure: import { CollapseProps } from &apo ...

Aurelia's navigation feature adds "?id=5" to the URL instead of "/5"

I have set up my Aurelia Router in app.ts using the configureRouter function like this: configureRouter(config, router: Router) { config.map([ { route: ['users', 'users/:userId?'], na ...

What is the best way to make the current tab stand out?

I have implemented a TabHeader component to create a dynamic Tab Menu that displays table contents based on months. The loop runs from the current month back to January, and the content is updated dynamically through an API call triggered by changes in the ...

Encountering a problem: The function _ctx.openNote is not recognized as a function when attempting to click on a note for viewing

I started with my notepad app from the ground up, which can be found on this link: Issues with data bind in vue.js and events The problem I encountered was that I couldn't click on the note from NoteList.vue to view the details. There seems to be a d ...

Creating an Angular Confirm feature using the craftpip library

Trying to utilize the angular-confirm library, but finding its documentation unclear. Implementing it as shown below: Library - In button click (login.component.ts), ButtonOnClickHandler() { angular.module('myApp', ['cp.ngConfirm']) ...

What is the best method for altering a route in React while utilizing Typescript?

I recently started coding along with the ZTM course and am working on a face recognition app. Instead of using JavaScript, I decided to use TypeScript for this project in order to avoid using the any type. However, as a beginner in this language, I'm ...

What is the method for adding a left border to a list that is currently active?

Is there a way to apply a left border to active lists using css? Check out this link for a code example <v-list-group v-for="item in items" :key="item.title" v-model="item.active" :prepend-icon="item.action" no-action> <template ...

Using Vue global variables within the <head> section of HTML documents

On my website, I am utilizing Vue version 2.6.11. In the src/main.js file, I have set some global variables based on guidance from this thread as shown below: /* global variables */ Vue.prototype.$frontUrl = "http://localhost:8080/"; Vue.prototyp ...

Encountering a Lint No Nested Ternary Error while utilizing the ternary operator

Is there a way to prevent the occurrence of the "no nested ternary" error in TypeScript? disablePortal options={ // eslint-disable-next-line no-nested-ternary units=== "mm&quo ...

Having trouble sending an email using nodejs and mailgun

Before accusing me of asking a duplicate question, I want to clarify that I have already searched for solutions and none of them worked for me. For example, I tried the solution provided in this link: Example of the domain name for mailgun before nodejs? ...