Obtain the return type of a typescript function based on the parameter type

I've come across various questions similar to the one about Typescript return type depending on parameter

However, my issue is slightly different: the parameter type is not a basic JS/TS type, but rather a class type. In this case of class types, the solution provided in the aforementioned question does not seem to work.

class Foo {}
class Bar {}

// My attempts

// 1.
function update<T extends Foo | Bar>(item: T): T extends Foo ? 'Foo' : 'Bar' {
  return {} as any
}

// 2.
function update(item: Foo): 'Foo'
function update(item: Bar): 'Bar'
function update(item: Foo | Bar): 'Foo' | 'Bar' {
  return {} as any
}

// Testing
const foo = new Foo()
const bar = new Bar()

const result1 = update(foo) // typeof result1: "Foo"
const result2 = update(bar) // typeof result2: "Foo", expected "Bar" however

The code above highlights my attempt to determine the return type of the function update() based on the parameter type, which can either be of type class Foo or class Bar. However, I have been unable to achieve the desired outcome. Any assistance would be greatly appreciated.

Answer №1

Your method of handling overloads is effective. However, a potential issue may arise if the classes are structurally equivalent, leading to the wrong overload being selected in the type system.

To ensure the expected behavior, introducing private fields to the classes can prevent aliasing and make them behave nominally:

class Foo { #foo = true }
class Bar { #bar = true}

function update(item: Foo): 'Foo'
function update(item: Bar): 'Bar'
function update(item: Foo | Bar): 'Foo' | 'Bar' {
  return {} as any
}

// testing
const foo = new Foo()
const bar = new Bar()

const result1 = update(foo) // typeof result1: "Foo"
const result2 = update(bar) // typeof result2: "Bar"

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

What is the best method for incorporating the three.js GLTFExporter into a TypeScript project?

I have been exploring the use of GLTFExporter in a three.js project written in TypeScript. I started with a basic template from https://github.com/pinqy520/three-typescript-starter and made modifications to the render function as follows: console.log(`typ ...

Step-by-step guide on how to stop CDK Drop depending on a certain condition

I'm trying to figure out how to disable dropping using CDK based on certain conditions. Specifically, I want the drop functionality to be disabled if the list I'm attempting to drop into is empty. I haven't been able to find a solution withi ...

Issue with rendering classes in Next.js: Why is a class being inadvertently applied to a different element?

When one element should be displayed while the other should not, they are given classes based on their relationship with each other. View code There is a login button component with a border gradient, along with an avatar component. Login button componen ...

Encountering a Next.js TypeScript Build Error related to the Type 'OmitWithTag<InputFormProps, keyof PageProps, "default">' issue

`I am currently working on a project in Next Js using TypeScript. During the build process with npm run build, I encountered the following errors in the terminal: # Type 'OmitWithTag<InputFormProps, keyof PageProps, "default">' do ...

Linking together observables to handle the response received from the PrimeNG confirmation service

Currently, I am utilizing the confirm.service from PrimeNG in my application. My goal is to display an array of messages to the user with only one message shown at a time along with an Accept button. However, my current code is only displaying the last me ...

Using TypeScript with Styled Components .attrs

I'm a bit perplexed about using the .attrs() function in conjunction with TypeScript. Let's consider the code snippet below: BottleBar.tsx: interface IBottleComponentProps { fill?: boolean } const BottleComponent = styled.div.attrs<IBottl ...

Determine the Variable Type by Evaluating the Value of Another Variable

I am looking to implement the following functionality: document("post").insert({ ... } /* TYPE SHOULD BE AUTOMATICALLY DETERMINED BY TYPESCRIPT */ ); The document() function returns an object that includes methods like insert. The returned objec ...

Unable to choose Typescript as a programming language on the VSCode platform

Recently, I encountered an issue while using Visual Studio Code with TypeScript. Even though TypeScript is installed globally, it is not showing up in the list of file languages for syntax highlighting. Despite trying various troubleshooting methods such a ...

Troubleshooting Angular 5: Interceptor Fails to Intercept Requests

I have a valid JWT token stored in local storage and an interceptor that I borrowed from a tutorial. However, the interceptor is not intercepting requests and adding headers as expected. Here's where I am making a request: https://github.com/Marred/ ...

Utilizing Angular to Transform an Array of Dates

I have an array of dates which returns: [Mon Aug 03 2020 00:00:00 GMT+0100 (British Summer Time), Wed Aug 05 2020 00:00:00 GMT+0100 (British Summer Time)] I am looking to convert these into the following format: ["2020-02-13T02:39:51.054", &quo ...

What causes the distinction between entities when accessing objects through TestingModule.get() and EntityManager in NestJS?

Issue: When using TestingModule.get() in NestJS, why do objects retrieved from getEntityManagerToken() and getRepositoryToken() refer to different entities? Explanation: The object obtained with getEntityManagerToken() represents an unmocked EntityManag ...

Experiencing difficulty creating query files for the apollo-graphql client

I'm currently attempting to learn from the Apollo GraphQL tutorial but I've hit a roadblock while trying to set up the Apollo Client. Upon executing npm run codegen, which resolves to apollo client:codegen --target typescript --watch, I encounter ...

What purpose does the NewableFunction interface serve?

An obscure built-in interface in TypeScript is VoidFunction, meant to represent functions that take no parameters and return void. Even more obscure is NewableFunction, which supposedly should represent functions that are "newable" or "constructable," but ...

Creating dynamic routing functionality in Angular 8 allows for a more personalized and

I am struggling with setting up routing in Angular 8. Here is how I am trying to do it: 'company/:id/activity' 'company/:id/contacts' However, I am not receiving any params in the activatedRoute: this.activateRoute.params ...

Using useRef with Typescript/Formik - a practical guide

Encountering Typescript errors while passing a ref property into my custom FieldInput for Formik validation. Specifically, in the function: const handleSubmitForm = ( values: FormValues, helpers: FormikHelpers<FormValues>, ) => { ...

Discover the potential of JavaScript's match object and unleash its power through

In the given data source, there is a key called 'isEdit' which has a boolean value. The column value in the data source matches the keys in the tempValues. After comparison, we check if the value of 'isEdit' from the data source is true ...

Class with abstract properties that are defined by its child classes

Is there a way to use TypeScript's abstract class to enforce defining functions and variables within the class for implementation? abstract class Animal { sound: string; speak() { console.log(this.sound); } } class Cat extends Animal { s ...

How can TypeScript leverage the power of JavaScript libraries?

As a newcomer to TypeScript, I apologize if this question seems simplistic. My goal is to incorporate JavaScript libraries into a .ts file while utilizing node.js for running my program via the console. In my previous experience with JavaScript, I utilize ...

Verify registration by sending an email to an alternate email address through Angular Firebase

I have implemented email verification for users before registration. However, I would like to receive a verification email to my own email address in order to finalize the registration process. I want to be notified via email and only after my approval sho ...

Ignore any information in NestJS that is not included in the data transfer object

In my NestJS controller, I have defined a route for updating locality information. The structure of the controller method is as follows: @Put('/:id') updateLocalityInfo( @Query('type') type: string, @Body() data: EditLocalityD ...