Ensuring the correct class type in a switch statement

It's been a while since I've used Typescript and I'm having trouble remembering how to properly type guard multiple classes within a switch statement.

class A {}
class B {}
class C {}

type OneOfThem = A | B | C;

function test(foo: OneOfThem): string {
    switch(/* something using foo */) {
        /* A */:
            return "A";
        /* B */:
            return "B";
        /* C */:
            return "C";

        /* should not need to use "default" as all cases are handled */
    }
}

I have tried various options, such as:

  • Using foo.constructor
  • Using instanceof inside the case statements
  • adding an extra member to the three classes to be used in the switch statement

but none of them seem to work (

Function lacks ending return statement and return type does not include 'undefined'
).

Am I mistaken in thinking that this cannot be done with classes?

Answer №1

Introducing an additional member to the three classes for utilization in the switch statement

This approach is likely the most straightforward solution for your scenario: it employs Discriminated Union. By including a discriminant member in each class, utilizing literal types (i.e. not just string or number), you can distinguish which class foo originates from:

class A {
    readonly kind = "a"
}
class B {
    kind: "b" = "b"
}
class C {
    kind = "c" as const
}

Subsequently, differentiate according to this kind discriminant property:

function test(foo: OneOfThem): string { // Alright
    switch (foo.kind) {
        case "a":
            foo
            return "A";
        case "b":
            foo
            return "B";
        case "c":
            foo
            return "C";
    }
}

Playground Link

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

Unable to locate the main source for loading

I am facing an issue with my app where I am unable to load a basic component. It seems like a simple problem, but I just can't seem to figure it out. Here is the code for my component: import { Component, OnInit } from '@angular/core'; imp ...

The path referenced in typings is incorrect

I am currently facing an issue with my Typescript library that I am trying to publish on npmjs. It seems like the types file is not being exported correctly. The library has a simple method in the src/index.ts file and typings from src/typings/index.d.ts. ...

"Extra loader required to manage output from these loaders." error encountered in React and Typescript

After successfully writing package 1 in Typescript and running mocha tests, I confidently pushed the code to a git provider. I then proceeded to pull the code via npm into package 2. However, when attempting to run React with Typescript on package 2, I enc ...

The Angular @Input directive may be prone to receiving inaccurate model data

I am currently working on setting up @Input for my component using a model that resembles the following: interface Car { sail?: never tires: number weight: number } interface Boat { tires?: never sail: boolean weight: number } exp ...

transitioning from angular cli version 1.7 to version 12

Looking for a detailed guide on upgrading from version 1.7 to the latest Angular version (12/11)? I currently have an app running on version 1.7 and couldn't find a step-by-step process here: upgrading angular Would it be safe to assume that the upgr ...

A guide to fetching and organizing an array of object identifiers using TypeScript

In my project, I am dealing with an array of objects named userRoles. The structure of this array is as follows: "userRoles": [ { "id": 1, "name": "Create", "description": "Th ...

Using C++ Empty Angle Brackets in a Template Class Return Function

While exploring a segment of libtorch (C++ PyTorch) code here, I came across an unfamiliar C++ syntax that caught my attention: Example<> get(size_t index); This snippet defines a function get, but what does it actually return? What exactly is Exam ...

What is the best way to implement callbacks with $http in Typescript?

When making my $http call, I am looking for the most adaptable way to handle all the parameters returned in the .success and .error functions. Here is an example of what my $http call looks like: this.$http({ url: "/api/x", method: "GET" }) .success((? ...

Tips for storing information in a JSON document?

I'm looking to save JSON data as a file with the extension .json by converting an object into a string using JSON.stringify This is what my code currently looks like: const jsonObject: object = { 'countryName': 'Switzerland&apos ...

An issue occurred in the modal window following the relocation of project files

I encountered an issue with the modal in my Nativescript project after rearranging a few project files, including the modal. I updated the imports and deleted any compiled JavaScript files to ensure that my project could recompile correctly. Although I&ap ...

Error encountered while initializing a C++ deque to read and store data within a class

Currently, I am in the process of reading a file and creating my own custom class to store data in a deque. The code snippet is as follows: class point{ public: void setX(float n) { x = n; } void setY(float m) { y = m; ...

Is there a way to ensure that the return type of a generic function is always optional in Typescript?

Is there a way to ensure the return type is always optional from a generic return type in functions? I specifically need the return types (data & error) to be optional at all times since one of them will always be undefined. TypeScript declarations i ...

flushMicrotasks does not function properly in conjunction with the image.onload event

Working on an Angular project, I'm currently developing an object with an image field. The method responsible for loading the image returns a promise that resolves in the onload function of the image. When trying to test this method using the flushMi ...

Angular Error TS2554: Received x arguments instead of the expected 0 on piped operators

I encountered an issue with Error TS2554: Expected 0 arguments, but got 4 when dealing with the observable getHappyDays(). The getHappyDays() Observable returns either Observable<HttpResponse<IHappyDays>> or Observable<HttpErrorResponse> ...

Creating an endless scrolling feature with Ionic 3

My tech stack includes symfony3 and FosRestBundle for the backend, and Ionic 3 for the frontend development. While attempting to implement an InfiniteScroll feature following the Ionic documentation, I encountered an issue where only the loading text and ...

Deducing data types from arrays containing both narrow and wide elements

const ElemText = { value: string }; const ElemData = { value: string, numId: number }; function combineElements( elementsText: Array<ElemText>, elementsData: Array<ElemData> ) { const combinedElements = [...elementsText, ...elementsData ...

What is the best method for compressing and decompressing JSON data using PHP?

Just to clarify, I am not attempting to compress in PHP but rather on the client side, and then decompress in PHP. My goal is to compress a JSON array that includes 5 base64 images and some text before sending it to my PHP API. I have experimented with l ...

What is the best way to implement this object builder in TypeScript strict mode without adding unnecessary weight to it?

After coming across a builder pattern online that I really liked, I found that it doesn't work in strict mode due to receiving the same error for the first 3 properties: (property) PizzaBuilder.numberOfSlices: number Property 'numberOfSlices&apo ...

Incorporating Ionic v3 with the latest StripeJS/Stripe Elements version 7.26.0

I have encountered two separate issues while trying to integrate the new version of Stripe into my Ionic v3 app. (Please refrain from suggesting an upgrade to Ionic v5, as it is currently not feasible for our team at this time!) Within my ionDidLoad funct ...

How can type annotations be properly incorporated into this TypeScript code using an inline function class?

How can I provide type annotations to inform TypeScript that this code is correct? Indeed, I do require that inline function class. The code presented here is a simplified version of my actual problem. let x = 10; const obj = new (function() { if(--x) r ...