What is the best way to dynamically include various properties in an object type depending on a generic union?

Consider the following union type:

type Union = "a" | "b";

Is there a way to add multiple new keys to an object type with conditions? Adding one key with a condition is straightforward:

type Condition<T extends Union> = {
  [K in T extends "a" ? "someProp" : never]: string;
}

type Result = Condition<"a">;

// type Result = {
//   someProp: string;
// }

However, attempting to add another key with a condition results in a syntax error:

type Condition<T extends Union> = {
  [K in T extends "a" ? "someProp" : never]: string;
  [K in T extends "a"? "anotherProp": never]: string;
//        ~~~~~~~      ~~~~~~~~~~~~        ~
}

Why does trying to perform two checks simultaneously not work here?

TypeScript Playground

Answer №1

You could implement a union in the condition within the index signature:

type Union = "a" | "b";

type Condition<T extends Union> = {
  [K in T extends "a" ? "someProp" | "anotherProp" : never]?: string;
}

const a: Condition<"a"> = {
  someProp: "foo",
  anotherProp: "foo",
}

Check it out on TypeScript 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

I am experiencing an issue with applying responsiveFontSize() to the new variants in Material UI Typography

I am looking to enhance the subtitles in MUI Typography by adding new variants using Typescript, as outlined in the documentation here. I have defined these new variants in a file named global.d.ts, alongside other customizations: // global.d.ts import * a ...

When attempting to utilize class validators in NestJS, Param is refusing to cast to DTO type

I'm currently working on implementing validation for the parameter I receive in a request, especially when trying to delete something. The parameter is expected to be a string but it must adhere to the format of a valid UUID. To achieve this, I have i ...

Can TestCafe be used to simulate pressing the key combination (Ctrl + +)?

I've been having a tough time trying to use the key combination specified in the title (Ctrl + +). So far, this is what I've attempted: 'ctrl+\+' 'ctrl+\\+' Does TestCafe even support this key combination? T ...

Error in TypeScript when using Google Maps React with Next.js: there is a possibility that infoWindow.close is undefined

Working on a small project in next.js (typescript) utilizing the google maps api with a KmlLayer. I want my map to interact with another component, SensorInfo. The current setup allows for smooth interaction between them - when SensorInfo is closed, the in ...

Prevent ESLint from linting files with non-standard extensions

My .estintrc.yaml: parser: "@typescript-eslint/parser" parserOptions: sourceType: module project: tsconfig.json tsconfigRootDir: ./ env: es6: true browser: true node: true mocha: true plugins: - "@typescript-eslint" D ...

What is the process for combining two interface declarations into a single interface?

I have a question regarding organizing the properties of an interface: export interface IInvoicesData { invoice: IInvoice; invoiceWithTotals: IInvoice & IInvoiceTotals; } Currently, everything is functioning smoothly and I am able to consolid ...

NGRX 8 reducer now outputting an Object rather than an Array

I am facing an issue where the data returned from the reducer is an object instead of an array. Despite trying to return action.recentSearches, it doesn't seem to work as expected. The data being returned looks like this: { "loading": false, "recent ...

Issue with React/Next.js input field rejecting commas

I'm experiencing a problem with an input field in my React application that was developed using Next.js. The issue arises specifically when using an iPad device, where the input field behaves inconsistently when dealing with commas. When using deskto ...

Tips for confirming a sub string is present in an array using JavaScript/TScript

I am currently testing for the presence of a SubString within an array. In my test, I am asserting using: expect(classList).toContain('Rail__focused') However, I encountered the following error: Error: expect(received).toContain(expected // inde ...

What is the process for converting a .ts file to a .js file within a Next.js project for Web worker implementation?

I am currently working on a TypeScript Next.js project: "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint& ...

Exploring NuxtJS Vuex Module namespaces and mutation enumerations

My NuxtJS website has a Vuex store with a root state and a module located at store/shop/cart/state.ts. Within the module, there is a file called store/shop/cart/mutations.ts. import { MutationTree } from 'vuex'; import { CartState } from './ ...

How can you loop through an array of objects in TypeScript without relying on the traditional forEach

Currently, I'm working on an array of objects with the following structure. [ { "matListParent": "CH", "dParent": "CUST1", "isAllSelected": true, "childItems&qu ...

When transmitting information to the server, the browser initiates four requests

I am encountering an issue with my React component. The problem arises when I try to retrieve the current geographic coordinates, as they are being fetched 4 times consecutively. This same glitch occurs when attempting to send the coordinates to the serv ...

Avoid using <input oninput="this.value = this.value.toUpperCase()" /> as it should not convert the text displayed on the "UI", rather it should send the uppercase value

<input oninput="this.value = this.value.toUpperCase()" type="text" id="roleName" name="roleName" class="form-control width200px" [(ngModel)]="role.roleName"> Even though the UI is changing ...

Implementing TypeScript type definitions for decorator middleware strategies

Node middlewares across various frameworks are something I am currently pondering. These middlewares typically enhance a request or response object by adding properties that can be utilized by subsequent registered middlewares. However, a disadvantage of ...

Stop any modifications to the input data

We are currently in the process of building an angular application with Angular 5. Typically, our components have input and output parameters defined as shown below: export class MultipleItemPickerComponent implements OnInit { @Input() itemPickerHeader ...

How can I incorporate the LIKE operator in a query when dealing with PostgreSQL's String array type using TypeORM?

My database backend is PostgreSQL and I have a TypeORM object simplified as follows: @Entity() @Index(['name'], {unique: true}) export class Foo extends BaseEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column() name: st ...

Tips for monitoring/faking method invocations within an Angular 5 service's constructor

My service involves making 2 method calls in the constructor: constructor(private http: HttpClient) { this.apiURL = environment.apiURL; this.method(); this.method2().subscribe(); } I am facing difficulties testing this service in the Test ...

What is the process for utilizing datePipe in an Angular component?

How can I implement DatePipe in my Angular component? This is the code snippet that I am currently using. for (let i = 0; i < this.days.length; i++) { this.storeStart(this.days[i], null, null, null); } I have stored weekdays (Monday to Frid ...

Changing the order of a list in TypeScript according to a property called 'rank'

I am currently working on a function to rearrange a list based on their rank property. Let's consider the following example: (my object also contains other properties) var array=[ {id:1,rank:2}, {id:18,rank:1}, {id:53,rank:3}, {id:3,rank:5}, {id:19,r ...