Using a Typescript-specific type within a switch case statement

I'm currently working on a function that, when given an enum value, should return a specific type. I am facing an issue where Typescript does not seem to recognize the properties inside switch and if statements.

interface X {
  x: string;
}

interface Y {
  y: string;
}

enum DataType {
  x = 'x',
  y = 'y',
}

interface Type {
  [DataType.x]: X;
  [DataType.y]: Y;
}

function customFunction<T extends keyof Type>(type: T): Type[T] {
  switch (type) {
    case DataType.x:
      return {x: 'example'}; // <--- Although there's no error, TS fails to recognize the property
  }
}

Developed with Typescript version 4.2.3.

Answer №1

Perhaps you may find function overloads to be a suitable solution. Should you opt for this approach, you will have to substitute interface Type with a specific overload signature for each scenario.

interface A {
  a: string;
}

interface B {
  b: string;
}

enum DataType {
  a = 'a',
  b = 'b',
}

function test(value: DataType.a): A;
function test(value: DataType.b): B; 
function test(value: DataType): A | B {
  switch (value) {
    case DataType.a:
      return {a: 'testA'};
    case DataType.b:
      return {b: 'testB'};
  }
}

TypeScript playground - live example

Answer №2

It appears that using a switch statement may not be the ideal approach due to typescript limitations, but there is an alternative solution available.

interface A {
  a: string;
}

interface B {
  b: string;
}

enum DataType {
  a = "a",
  b = "b",
}

interface Type {
  [DataType.a]: A;
  [DataType.b]: B;
}

function test<T extends keyof Type>(type: T): Type[T] {
  return (type === DataType.a ? { a: "test" } : { b: "test" }) as Type[T];
}

Answer №3

When dealing with a set of related Types where differentiation is crucial, it is recommended to use a dedicated property for this purpose - TypeScript is designed for optimal performance in such scenarios. For instance:

type KindValues = "a" | "b"

type TT = {
  kind:KindValues,
  body: any
}

type TA = {
  kind:"a",
  body:string
}
function isTA(t:TT):t is TA { return t.kind==="a"; }

type TB = {
  kind:"b",
  body:number
}
function isTB(t:TT):t is TB { return t.kind==="b"; }

function handler(t:TT):void{
  if (isTA(t)){
    //t.body=1  // error: number is not assignable to string
    t.body = 'x';
  }
  else if (isTB(t)){
    //t.body='x'  // error: string is not assignable to number
    t.body = 1;
  }
}

To avoid excessive type checks, it is often more versatile to establish a Map linking kind to corresponding functions.

While TypeScript does not mandate a single discriminator key, it performs efficiently even with an additional key for subtyping types. However, keeping the keys minimal enhances auto-completion capabilities.

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

Creating encoded objects for a content-type of `application/x-www-form-urlencoded`

Upgrading AngularJS Code to Angular 2+ - Http Issue I am in the process of converting some legacy AngularJS code (specifically Ionic 1) to the latest version of Angular (Ionic 4), and I've encountered a troubling issue. Previously, in every HTTP POS ...

SwitchMap in Typescript allows you to switch to a

In my TypeScript code, I have implemented multiple interfaces, components, and a key/interface map. interface FooProps { 'keyInFoo': string } const Foo = (props: FooProps) => {} interface BarProps { 'keyInBar': string } cons ...

What steps should I take to import a module with type definitions? (receiving error TS2656: ...not a module)

I am currently working on enhancing the type definitions for a simple npm module called emitter20. The source code of this module spans 20 lines and looks like this: module.exports = function() { var subscribers = [] return { on: function (eventNa ...

Update each number in an array by appending a string within a table in an Angular component, rather than the

I have created a function that decides on a comment based on the result number added to an array and displays it in a table. However, calling this function within the template is causing a performance slowdown. Is there a way to achieve the same outcome w ...

Using JSDoc to Include TypeScript Definitions

I've been attempting to utilize the ts-xor package, which provides a TypeScript definition: export declare type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U; This is how I'm imp ...

Using TypeScript to return an empty promise with specified types

Here is my function signature: const getJobsForDate = async (selectedDate: string): Promise<Job[]> I retrieve the data from the database and return a promise. If the parameter selectedDate === "", I aim to return an empty Promise<Job[] ...

Learn how to connect a formArray from the parent component to the child component in Angular with reactive forms, allowing you to easily modify the values within the formArray

In my parent component, there is a reactive form with controls and a form group. When the user selects a playerType from a dropdown menu, I dynamically add a formArray to the formGroup. This form array will contain either 2 or 3 form groups based on the p ...

Ways to retrieve the quantity of a particular value within an object using TypeScript

I'm inquiring about how to retrieve the number of a specific value within an object using TypeScript. Here is the structure of the object: obj : TestObject = { name: "test", street: "test" subobj1: { status: warning, time: ...

show additional worth on the console

Just starting out with JavaScript. Trying to display additional values in the console. Uncertain about how to access add-ons. Can anyone help me troubleshoot? Here is my code snippet below: https://jsfiddle.net/6f8upe80/ private sports: any = { ...

Component not appearing in Storybook during rendering

I'm trying to incorporate the MUI Button Component into my storybook and then dynamically change MUI attributes like variant, color, and disabled status directly from the storybook. While I was successful in doing this with a simple plain HTML button, ...

What is the proper way to define the scope for invoking the Google People API using JavaScript?

I am attempting to display a list of directory people from my Google account. export class People { private auth: Auth.OAuth2Client; private initialized: boolean = false; private accessToken: string; constructor(private readonly clientEmail: strin ...

I attempted to execute an art configuration on Metaplex, but I keep encountering the same issue. Despite numerous attempts to modify various settings, the problem persists

Error encountered while compiling TypeScript code on desktop using ts-node to generate art configuration traits: Unable to find module 'commander' or its corresponding type declarations. Unable to find module '@project-serum/anchor' or ...

Troubleshooting Date library timezone problems in Typescript locale

The TZ variable is automatically set by Node as an environment variable. When using new Date(); in TypeScript, the date returned is in GMT+0000 even though the code is being executed on a machine with a timezone of GMT+0530. I attempted to print out conso ...

Unable to use console log in shorthand arrow function while working with Typescript

When debugging an arrow function in JavaScript, you can write it like this: const sum = (a, b) => console.log(a, b) || a + b; This code will first log a and b to the console and then return the actual result of the function. However, when using TypeSc ...

Separate the string by commas, excluding any commas that are within quotation marks - javascript

While similar questions have been asked in this forum before, my specific requirement differs slightly. Apologies if this causes any confusion. The string I am working with is as follows - myString = " "123","ABC", "ABC,DEF", "GHI" " My goal is to spli ...

Organizing a mat-table by date does not properly arrange the rows

My API retrieves a list of records for me. I would like to display these records sorted by date, with the latest record appearing at the top. However, the TypeScript code I have written does not seem to be ordering my rows correctly. Can anyone assist me ...

Matching packages with mismatched @types in Webpack 2: A comprehensive guide

Having trouble implementing SoundJS (from the createJS framework) in my TypeScript project using webpack 2. In my vendors.ts file, I have the following import: import "soundjs"; Among other successful imports. The @types definitions installed via npm a ...

Using Angular components to manipulate the CSS in the DOM

Struggling with dom manipulation in an angular/node.js environment using typescript for my visualcomponent.html The second inline styling works fine, showing the h1 in blue color. However, I run into issues when trying to embed strings within the innerHTM ...

Utilizing a mutual RxJS subject for seamless two-way data binding in Angular 2

I have a unique service dedicated to managing app configurations class Configuration { get setting() { return dataStore.fetchSetting(); } set setting(value) { dataStore.saveSetting(value); } } This configuration is linked to components t ...

Issue with rendering React Toastify

I'm running into an issue while trying to integrate react toastify into my react vite application. Specifically, I keep getting an error related to useSyncExternalStore even after attempting to switch to version 9 of react toastify. My React version i ...