Tips for accessing the properties of a union type function

When dealing with this scenario, What should the test() function's generic be?

interface A {
    type: 'a' ;
    state: number;
}

interface B {
    type :'b',
    state: string;
}

type OneOfThem = A | B;

function test<T extends OneOfThem>(type: T['type'], state: T["state"]): T {
    return {type, state} as T
}
test('a', 3) // it should not generate an error
test('a', "asd") // it should result in an error

In this instance, the test function's types are operating like

function test<OneOfThem>(type: "a" | "b", state: string | number): OneOfThem

therefore, neither of these expressions throw errors.

Answer №1

One way to differentiate between Union Members is by utilizing a Conditional Type. You can achieve this by using the built-in type Extract in TypeScript. Keep in mind that the generic should be a subtype of OneOfThem["type"], not just OneOfThem.

interface A {
  type: "a";
  state: number;
}

interface B {
  type: "b";
  state: string;
}

type OneOfThem = A | B;

function test<T extends OneOfThem["type"]>(
  type: T,
  state: Extract<OneOfThem, { type: T }>["state"],
): Extract<OneOfThem, { type: T }> {
  return { type, state } as Extract<OneOfThem, { type: T }>;
}

test("a", 3); // valid
test("a", "asd");
//        ~~~~~ Argument of type 'string' is not assignable to parameter of type 'number'.

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

Can an empty form group be defined and then have form controls added later within the onInit function?

Can someone help me with declaring an empty form group and then adding form controls afterwards? I have tried passing in a null value or not passing anything at all, but it doesn't seem to work. this.demoForm = new FormGroup(null);//NOT WORKING Is th ...

Using Typescript, the type T or a function that returns T can be utilized in various scenarios

You can check out a demonstration on this interactive platform. In creating a simple generic type that represents either a variable or a function returning a variable, there was an issue with the typical typeof arg === 'function' check. The erro ...

Arrange information in table format using Angular Material

I have successfully set up a component in Angular and Material. The data I need is accessible through the BitBucket status API: However, I am facing an issue with enabling column sorting for all 3 columns using default settings. Any help or guidance on th ...

Having trouble converting the JSON object received from the server into the necessary type to analyze the data

I am new to angular and struggling with converting a JSON object from the server into a custom datatype to render in HTML using ngFor. Any help would be appreciated as I have tried multiple approaches without success. Apologies for the simple HTML page, I ...

Can we handle optional properties that are contingent on a boolean in the type?

My current scenario involves a server response containing a boolean indicating success and optional data or error information. type ServerResponse = { success: boolean; data?: { [key: string]: string }; err?: { code: number, message: string }; } Dea ...

Downcasting on "this" is not supported in Typescript

In the example below, the TypeScript compiler does not allow for a direct cast of this to Child. However, it is possible to achieve this using an intermediate variable like 'temp' or double casting as shown in the commented lines. Is this behavio ...

What could be causing my Page to not update when the Context changes?

In my Base Context, I store essential information like the current logged-in user. I have a User Page that should display this information but fails to re-render when the Context changes. Initially, the Context is empty (isLoaded = false). Once the init fu ...

Automated Excel Script for Deleting Rows Containing Highlighted Cells

Does anyone have a solution for removing rows from a table in an office script that contain highlighted cells? I attempted to filter rows with highlighted cells using the recorder, but it showed 'This action is not yet recordable.' If you have a ...

Encountering a premature closure error, specifically the inability to set headers after they have already been sent to the client, when trying to stream video

I am in the process of constructing a video streaming web server with Nestjs. I have diligently followed the steps outlined in the Nest documentation. Unfortunately, I encountered some errors... MY file.controller.ts import { Controller ...

Issue: "The specified function type '(num: number) => number' cannot be assigned to type 'number'.(2322)"

Whenever I use a function like this, everything works smoothly: const roundToTwo = (num: number) => { return +(Math.round(+(num + "e+2")) + "e-2"); }; Upon hovering over the function name in VS Code, I can observe that it returns ...

A guide to setting properties using a Proxy object

Within my class, I have included a Proxy which is structured as follows: export class Row<T extends ModelItems> { private _row: T = <T>{} public constructor(rowItems?: T) { if (rowItems) { this._row = rowItems } return new Proxy( ...

NestJS Exporting: Establishing a connection for PostgreSQL multi tenancy

I have been working on implementing a multi tenancy architecture using postgres. The functionality is all in place within the tenant service, but now I need to import this connection into a different module called shops. Can anyone provide guidance on how ...

The async/await feature in Typescript fails to trigger updates in the AngularJS view

Currently, I am utilizing Typescript 2.1 (developer version) to transpile async/await to ES5. An issue I have encountered is that when I modify any property linked to the view within my async function, the view does not automatically reflect the updated v ...

Encountering TypeScript error TS2339 while trying to utilize a method from a different class within an event handler and binding the current

My development setup includes a service called DomService for all DOM manipulation tasks. Additionally, I have another service called ModalService that handles modal functionality. Within the ModalService, there are some events being bound, with a method ...

In ReactJS, the way to submit a form using OnChange is by utilizing the

Is there a way to submit a form using Onchange without a button? I need to fire the form but can't insert routes as it's a component for multiple clients. My project is built using react hook forms. const handleChange = (e: any) => { c ...

Sending various kinds of generic types to React component properties

Currently, my team and I are working on a TypeScript/React project that involves creating a versatile 'Wizard' component for multi-step processes. This Wizard acts as a container, receiving an array of 'panel' component properties and p ...

In Angular 5, you can easily prevent interaction with a related button by disabling it when the corresponding reactive

I recently encountered a situation where I needed to implement a reactive form in a component. It looked something like this... form component.html <form [formGroup]="form" class="do-form"> <div formGroupName="dot"> <div class ...

Managing Keyboard Input in React using TypeScript

Hey there! I'm currently working on a method that should automatically insert a specific string into a textbox when a particular key is pressed. The key in question is a non-printable character that may not be visible in most font styles, but can sti ...

Tips for accessing the data type of a nested property in TypeScript

If I want to keep the following declarations as they are, how can I specifically retrieve the type of the members property? export type Members = { __typename?: 'Members'; id?: Maybe<Scalars['String']>; ... }; export type P ...

Is there a way to set up TS so that it doesn't transpile when an error occurs?

Is there a way to configure my tsconfig.json file in order to prevent transpiling if an error occurs? I have searched the documentation but couldn't find any flag or configuration for this. Does anyone know how I can achieve this? ...