What is the proper syntax for specifying a specific field in a generic class?

type Specific = {field: 'add'} | {field:'remove'};

function add(value: Specific) {} // Ensures value.field === 'add'
function remove(value: Specific) {} // Ensures value.field === 'remove'

How can I restrict functions add and remove to only accept values with the exact field='add' or field='remove' values?

I am using zod infer on union and would like the functions to only accept one specific type from the union without splitting them into different types.

Answer №1

To extract your desired object types from the Union Some, you can utilize the Extract method in the following way:

type Some = { field: "add" } | { field: "remove" };

declare function add(value: Extract<Some, { field: "add" }>): void; 
//                   ^? value: { field: "add"; }
declare function remove(value: Extract<Some, { field: "remove" }>): void; 
//                      ^? value: { field: "remove"; }

For a scenario where Some includes additional properties like:

type Some =
  | { field: "add"; property2: string }
  | { field: "remove"; property2: number };

there may be unexpected properties extracted:

declare function add(value: Extract<Some, { field: "add" }>): void;
declare function remove(value: Extract<Some, { field: "remove" }>): void;

add({ field: "add" });
//   ~~~~~ Property 'property2' is missing in type '{ field: "add"; }' ...

Explore more on this in the TypeScript Playground


Alternatively, you can opt for object literal types. This method is more straightforward, but it disconnects from the original union Some, making it less resilient to future name changes in the field property without compiler warnings.

type Some = { field: "add" } | { field: "remove" };

declare function add(value: { field: "add" }): void;
//                   ^? value: { field: "add"; }
declare function remove(value: { field: "remove" }): void;
//                      ^? value: { field: "remove"; }

While the object literal approach is simpler, I personally find it more error-prone compared to using Extract.

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

Streamlined Authorization in MEAN (SPA) Applications

I have created an application, but now I am trying to adapt it into a SPA application. The main issue I am facing is with the Authorization process. While I can successfully register new users, log them in, and retrieve their tokens, I seem to encounter a ...

The properties are absent in Angular Service - Observable

I recently started learning angular and I'm struggling to make this HTTP get request work. I have been looking at various examples of get requests for arrays and attempted to modify one for a single object (a user profile) but without success. The err ...

Converting keyValue format into an Array in Angular using Typescript

Is there a way to change the key-value pair format into an array? I have received data in the following format and need to convert it into an array within a .TS file. countryNew: { IN: 159201 BD: 82500 PK: 14237 UA: 486 RU: 9825 } This needs to be transf ...

The utility of commander.js demonstrated in a straightforward example: utilizing a single file argument

Many developers rely on the commander npm package for command-line parsing. I am considering using it as well due to its advanced functionality, such as commands, help, and option flags. For my initial program version, I only require commander to parse ar ...

Jasmine Destiny - Error Encountered: macroTask 'setTimeout': unable to switch to 'active' state, expecting 'planned' state, but it was 'notScheduled'

I am currently using Angular 7 with the Zone.js version of approximately ~0.8.26. Inside my test.ts file, I have included the import statement for 'zone.js/dist/zone-testing'. Below is a snippet from my spec file: import { HttpClientTestingModul ...

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 ...

Ways to update the value within an object in an array stored in a BehaviorSubject?

My initial data is: const menuItems = [{id: 1, active: false}, {id: 2, active: false}] public menuSubject$ = new BehaviorSubject<MenuItem[]>(menuItems); public menu$ = this.menuSubject$.asObservable(); I am attempting to update the element with ...

Typescript Rest API requests are experiencing issues when made with vscode version 1.82.2

Whenever I try to make Rest API calls in Typescript, I encounter the following error: error code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' message: 'unable to get local issuer certificate' Our API Calls were functioning properly up until vs ...

The custom validation in nestjs is throwing an error due to an undefined entity manager

I've been working on developing a custom validation for ensuring unique values in all tables, but I encountered this error: ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'getRepository') TypeError: Cannot read proper ...

Restrict the object field type to an array by analyzing control-flow for accessing elements within brackets

Enhancements in type narrowing using control-flow analysis for bracket element access have been introduced in TypeScript 4.7. One thing I'd like to do is verify if the accessed field is an array or not. Currently, the type guard seems to be ineffecti ...

formBuilder does not exist as a function

Description: Using the Form Builder library for react based on provided documentation, I successfully implemented a custom fields feature in a previous project. This project utilized simple JavaScript with a .js extension and achieved the desired result. ...

Dealing with a situation where different functions need to be called based on a condition while using unique button names. This is

<button type="button" class="btn btn-primary ms-4" (click)="update()">Save</button> <button type="button" class="btn btn-primary ms-4" (click)="create()">Add</button> B ...

Is there a method of converting React components into strings for manipulation?

In my React TypeScript project, I am utilizing a crucial library that contains a component which transforms text into SVG. Let's refer to this library component as <LibraryRenderer />. To enhance the functionality, I have enclosed this componen ...

Tips for managing update logic in the server side with sveltekit

Currently, I am using Sveltekit and I am facing a dilemma regarding updating input data. The actual update process is straightforward, but there is an issue that arises when trying to send an update API request immediately, as it requires an accessToken to ...

Restrict the discriminator value in a discriminated union from any other string literal union type in TypeScript

My discriminated union is quite basic, but I want to restrict the discriminator to only allow specific values that come from another string literal union type. This would simplify the process of adding new "cases" to the discriminated union. Here is a str ...

Getting environment variables on the client side in Next.js: A step-by-step guide

How can I retrieve an environment variable in my Next.js application and pass the data into datadogRum.init? // _app.tsx import React from "react"; import { useEffect } from "react"; import type { AppProps } from "next/app"; ...

Navigate to the logout page upon encountering an error during the request

I recently upgraded our application from angular 2 to angular 5 and also made the switch from the deprecated Http module to the new HttpClient. In the previous version of the application, I used the Http-Client to redirect to a specific page in case of er ...

Combining Axios with repeated promises

I am facing an issue with a loop in my GET request on the axis, and I cannot figure out why. const [ state, setState ] = useState<any[]>([]); ids.forEach((id) => { getData(id) .then((smth: Map<string, any>[]) => getNeededData ...

Using TypeScript to structure and organize data in order to reduce the amount of overly complex code blocks

Within my TypeScript module, I have multiple array structures each intended to store distinct data sets. var monthlySheetP = [ ['Year', 'Month', 'Program', 'Region', 'Market', 'Country', &apo ...

How to add a service to a static function in Angular

After incorporating a logger service into my project, I have encountered an issue with using it in NGXS static selectors. The selectors in NGXS are static methods, which prevent me from accessing the logger service injected via Angular DI. Are there any e ...