Finding the specific type within a union based on its field type

I am trying to implement a function sendCommand that returns a value of type specified by the union InputActions, selected based on the action_id type. Below is my code snippet:

interface OutputAction1 {
  command: 'start',
  params: string;
}

interface OutputAction2 {
  command: 'end'
  data: string;
}

type OutputActions = OutputAction1 | OutputAction2;

interface InputAction1 {
  action_id: 'start',
  token: string
}

interface InputAction2 {
  action_id: 'end',
  userData: string
}


type InputActions = InputAction1 | InputAction2;

const sendCommand = (action: OutputActions): Extract<InputActions, {action_id: OutputActions['command']}> => {
    return action.command === 'start' ? {
      action_id: 'start',
      token: '123'
    }:{
    action_id: 'end',
    userData: '123'
    }
 
}

let k = sendCommand({command: 'start', params: ''})
k.token // Property 'token' does not exist on type 'InputAction2'

I expect variable k to have type InputAction1, however it currently has type InputActions. Is there a way to inform TypeScript to infer the expected type based on the action_id from the arguments?

Sandbox

Answer №1

In my opinion, opting for Function Overloads would be the best choice here to keep things simple. The correct return type will be automatically inferred.

function sendCommand(action: OutputAction1): InputAction1;
function sendCommand(action: OutputAction2): InputAction2;
function sendCommand(action: OutputActions) {
  return action.command === "start"
    ? {
        action_id: "start",
        token: "123"
      }
    : {
        action_id: "end",
        userData: "123"
      };
}

let k = sendCommand({command: "start", params: ""});
// let k: InputAction1

let k2 = sendCommand({command: "end", data: ""});
// let k2: InputAction2

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

Could this type declaration in the Vue decorator constructor be accurate?

When using Vue decorator notation, I typically write it like this: @Prop({ type: Object || null, default: null }) However, I noticed in the Vue documentation that they use array notation: @Prop({ type: [ Object, null ], default: null }) Is there a specif ...

Struggling to utilize a custom react-three-fiber component despite specifying the custom type within the react-three-fiber module

Currently developing a react application focused on visualizing mathematical concepts with the help of react-three-fiber. Utilizing TypeScript, I discovered that by extending custom ThreeElements (https://docs.pmnd.rs/react-three-fiber/tutorials/typescript ...

retrieve user input from various angular 6 components

Currently, I am in the process of developing a small web-based game using Angular 6. Within this project, I have two key components - play.component and setup.component. The main concept is to allow users to customize elements such as difficulty within the ...

Angular 2 allows for duplication of elements using drag and drop functionality

Check out my code on Plunker for drag and drop functionality in drag.ts: http://plnkr.co/edit/PITLKzBB6YXobR1gubOw?p=preview. Please note that it only works in a separate window preview. import {Component, OnInit, ElementRef, Renderer} from '@angular ...

Using Typescript: Defining a function parameter that can be either of two interfaces

While browsing through this specific question, I noticed that it was somewhat related to my current issue, although there were notable differences. In my scenario, I have a function named parseScanResults which accepts an object as its argument. This obje ...

Absence of property persists despite the use of null coalescing and optional chaining

Having some trouble with a piece of code that utilizes optional chaining and null coalescing. Despite this, I am confused as to why it is still flagging an error about the property not existing. See image below for more details: The error message display ...

Error message 2339 - The property 'toggleExpand' is not recognized on the specified type 'AccHeaderContextProps | undefined'

When utilizing the context to share data, I am encountering a type error in TypeScript stating Property 'toggleExpand' does not exist on type 'AccHeaderContextProps | undefined'.ts(2339). However, all the props have been declared. inter ...

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

When incorporating a JS React component in TypeScript, an error may occur stating that the JSX element type 'MyComponent' is not a valid constructor function for JSX elements

Currently, I am dealing with a JavaScript legacy project that utilizes the React framework. Within this project, there are React components defined which I wish to reuse in a completely different TypeScript React project. The JavaScript React component is ...

TS2531: Nullability detected in object when using .match() method

I'm encountering a linting error on fileNameMatches[0] in the following code snippet. Strangely, the error doesn't appear on the Boolean() check. Even if I remove that check, the issue remains unresolved. Can anyone suggest a solution? protected ...

Encountering issues with importing a module from a .ts file

Although I have experience building reactJS projects in the past, this time I decided to use Node for a specific task that required running a command from the command line. However, I am currently facing difficulties with importing functions from other fil ...

having difficulty applying a border to the popup modal

Currently, I am utilizing a Popup modal component provided by the reactjs-popup library. export default () => ( <Popup trigger={<button className="button"> Guide </button>} modal nested > {(close: any) =&g ...

What are the steps to styling a component with CSS Emotion?

I am facing an issue with using a theme with TypeScript in this component const buttonDisabled = css` color: ${({ theme }) => theme.color}; `; Is there a way to correctly type this component? Error: No overload matches this call. Overload 1 of 2, & ...

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 viewing a React data table in Chromium browsers, the columns on the right side may flicker when the screen is small or the browser

I recently integrated the React data grid Npm package by adazzle. You can find more information about it here. I encountered an issue which you can see in this example: https://codesandbox.io/s/react-data-grid-example-9sb93?file=/src/App.tsx When using a ...

A guide on leveraging typeof within function parameters to ensure accurate variances

Let's create a simple class hierarchy and a list of instances. The goal is to filter items from the list of instances based on their class. There are a couple of challenges: We cannot use the typeof T syntax. How can this be written? We cannot decla ...

Tips for accessing touch events within the parent component's area in React Native

I implemented the code below in my React Native app to disable touch functionality on a specific child component. However, I encountered an issue where the touch event was not being detected within the area of the child component. How can I fix this prob ...

Issue with npm resolution due to package requiring another third-party dependency

I'm encountering an issue with a requirement and I'm hoping for some assistance. I currently have a package called @unicoderns/orm that relies on mysql, which can be found at https://github.com/unicoderns/ORM Now I'm working on developing ...

Utilizing PrimeNG's p-dataView feature without repetitive FieldSets

Currently, I am utilizing p-dataView and I'm interested in implementing p-fieldset based on the application type. My goal is to prevent the fieldset from being duplicated when multiple instances occur. The scenario below illustrates one such case; how ...

Revamp your search experience with Algolia's Angular Instant Search: Design a personalized search box template

Custom Search Box Request: My goal is to implement an autosuggest search box using Algolia Angular instant search with an Angular Material design. To achieve this, I am planning to customize the search box component by replacing the standard <ais-sea ...