How to dynamically assign a type based on a single choice from multiple options (props)

I have a props object that includes:

{
option1,
option2,
option3,
option4,
general,
otherProps
}

The requirement is to allow only one option to be used at a time. Here are the types defined:

interface MyTypes {
 option1: boolean
 option2: boolean
 option3: boolean
 general: boolean
 otherProps: string
}

This is my attempt:

interface GeneralTypes{
 general: boolean
 otherProps: string
}

interface Option1Types{
 option1: boolean
}
interface Option2Types{
 option2: boolean
}
interface Option3Types{
 option3: boolean
}
 
type MyTypes = GeneralTypes & (Option1Types | Option2Types | Option3Types)

However, I encounter this error:

Property 'option1' does not exist on type '(GeneralTypes & Option1) | (GeneralTypes & Option2)| (GeneralTypes & Option3)'
Property 'option2' does not exist on type '(GeneralTypes & Option1) | (GeneralTypes & Option2)| (GeneralTypes & Option3)'
Property 'option3' does not exist on type '(GeneralTypes & Option1) | (GeneralTypes & Option2)| (GeneralTypes & Option3)'

Answer №1

When I need to set only one property, here is the solution I found.

type RequireOnlyOne<T, Keys extends keyof T = keyof T> =
  Pick<T, Exclude<keyof T, Keys>>
  & {
    [K in Keys]-?:
    Required<Pick<T, K>>
    & Partial<Record<Exclude<Keys, K>, undefined>>
  }[Keys]

interface GeneralTypes {
  general: boolean
  otherprops: string
}

type MyTypes = GeneralTypes & RequireOnlyOne<{
  option1: boolean,
  option2: boolean,
  option3: boolean,
}>

const props: MyTypes = {
  general: false,
  otherprops: '',
  option1: true,
}

You can find a detailed explanation here.

Answer №2

const MergeToUnion<M> =
  (M extends any ? (u: M) => void : never) extends ((u: infer U) => void) ? U : never

const UniqueMerge<U> =
  | MergeToUnion<U> extends infer Y ? (
    U extends any ?
    U & { [k in Exclude<keyof Y, keyof U>]?: never }
    : never
  ) : never

const result = UniqueMerge<UserTypes>
// const result = (SpecificTypes & Example1Types & {
//     example2: never;
//     example3: never;
// }) | (SpecificTypes & Example2Types & {
//     example1: never;
//     example3: never;
// }) | (SpecificTypes & ... 1 more ... & {
//     ...;
// })

const variable: result = UserObject;
if (variable.example1) {
  variable; // SpecificTypes & Example1Types
}

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

Error in MatSort implementation - Argument cannot be assigned

I'm having trouble figuring out how to implement the Mat-Sort functionality from Angular Material. When I try to declare my variable dataSource, I get the following error: Argument of type 'Observable' is not assignable to parameter of type ...

In Typescript, an interface is defined where the "id" property is required to be a number, while all other properties must be of

I am in need of creating an interface to represent data received from the server, where the id is a number and all other properties are strings. This is what I attempted: interface AnyChartsData { id: number; [key: string]: string; } However, I enco ...

Why are mustaches not functioning as expected in Vue SFC defined by Vite?

I recently ran into a configuration issue with my vite-config.ts file. export default defineConfig({ ... define: { __PRODUCT__: JSON.stringify("My Product") } In my vue sfc template, I have the following code snippet: <div class="footer"> {{ ...

Issue TS2769: No matching overload found for this call. The type 'string | null' cannot be assigned to type 'string | string[]'

export class AuthService { constructor(private http: HttpClient, private webService: WebRequestService, private router: Router) { } login(email: string, password: string) { return this.webService.login(email, password).pipe( shareReplay(), ...

Display a modal dialogue with an image on the initial page load for each user

Working on a project with Angular 11, Angular material, and Bootstrap, I encountered an issue. I want to display a popup ad the first time a user visits the home page. The modal dialog is created using Angular material, and I have it in the ads component, ...

Typescript error: Cannot assign type 'undefined' to type 'string | number | symbol'

I need help figuring out how to address a TypeScript error in my code. Here's the scenario: export type status = 'success' | 'error' | undefined; There is an object that maps to different icons based on the status. const iconsMap: ...

Discover the step-by-step guide to setting up forwarding in React Router 5

Just diving into the world of React and TypeScript. I'm working with a component called Err. Is there a way to redirect it using React Router 5? import React, { FC, Fragment, useEffect } from "react"; const Err: FC<{ error: string }> = ({ erro ...

Troubleshooting Clarifai object error while invoking "model.predict" within Angular Framework

I've been attempting to utilize Clarifai's color API to extract the different colors present in an image. Unfortunately, I am encountering challenges when trying to call the API, as it consistently returns empty objects. Below is the snippet of ...

Trigger a class method in an event using Angular with Typescript

I am completely new to TypeScript and Angular, and I am attempting to create a basic drawing component on a canvas. However, I have reached a point where I feel lost and confused about my code. The concept of "this" in TypeScript has been a major stumbling ...

Nextjs 13 brings exciting new features, one of which is the ability to call getStatic

I am working on a Next.js 13 application where I have organized my files in the 'app' directory instead of the usual 'pages'. All pages are statically generated during build time and data is fetched from an external API. Everything wor ...

Learn how to merge two objects and return the resulting object using TypeScript functions within the Palantir platform

I am looking to generate a pivot table by combining data from two objects using TypeScript functions. My plan is to first join the two objects, create a unified object, and then perform groupBy operations along with aggregate functions like sum and min on ...

Enhance Material UI with custom properties

Is it possible to add custom props to a Material UI component? I am looking to include additional props beyond what is provided by the API for a specific component. For example, when using Link: https://material-ui.com/api/link/ According to the document ...

Encountering issues with TypeScript class

I am facing an issue with transpiling the following TypeScript class: class DataService { styles: Object[]; selectedStyle: Object; selectedChildStyle: Object; constructor() { this.styles = [{ "name": " ...

The argument represented by 'T' does not align with the parameter represented by 'number' and therefore cannot be assigned

I am confused as to why, in my situation, <T> is considered a number but cannot be assigned to a parameter of type number. Changing the type of n to either number or any resolves the issue. Error: Code: const dropFoo = <T>(arr: T[], n: T): T ...

Implement real-time word counting in Angular as users type

I am looking to monitor word count in real-time as a user enters text into a textarea field If the word limit of 100 is exceeded, further typing should be restricted I aim to display the word count dynamically as the user types wordCounter() This functi ...

Using React with Typescript to display components generated from the `map` function

In my scenario, I have retrieved data from a JSON file and am also utilizing a utility function that selects 5 random entities from an object Array. This particular array contains 30 entities. Struggling with displaying the 5 random jockeys stored in the ...

What is the best way to change between different Angular 2 material tabs using typescript?

I need help with switching tabs using buttons <md-tab-group> <md-tab label="Tab 1">Content 1</md-tab> <md-tab label="Tab 2">Content 2</md-tab> </md-tab-group> <button md-button (click)="showTab1()">Show Tab 1< ...

Angular 2 date validation rule for dd/mm/yyyy format in forms with reactive functionality

this.seedFundForm = this.fb.group({ multipleSource: this.fb.array([]), amount:[data.amount, Validators.compose([Validators.required, Validators.pattern('[0-9]*'), Validators.maxLength(10)])], date:[data.date, Validators.compose([Valid ...

What is the best approach for conducting unit tests on model interfaces with TypeScript?

export interface Person { fullName: string; } What is the best way to create unit tests for the above interface and ensure that Karma includes it in the code coverage report? I attempted to assert properties by creating an object, but it seems that K ...

update the data source of the material table inside the subscription

Seeking guidance for updating a MatTable datasource within an Angular application. The current Typescript code involves fetching data from an API using AdminService, iterating over the results to make additional API calls for more information about a fleet ...