Deduce the output data type of a function by having knowledge of a single property

Is there a way to achieve this without using if/else or switch statements by utilizing function return values?

interface test1 {
    type: 'test1'
}

interface test2 {
    type: 'test2'
}

type unType = test1 | test2;

//I am aware of the property "type"'s value
//Can I use this information to determine the specific type (test1 or test2) in a function's return value?
function whichType<T>(typeValue): T {

    return null;
}

const tt1 = whichType<unType>('test1');// expected output: interface test1
const tt2 = whichType<unType>('test2');// expected output: interface test2

Answer №1

To implement overloads as suggested by TJ Crowder is an effective approach, especially when dealing with a limited number of interfaces. It is straightforward to write and understand.

For a more versatile solution, one can utilize the Extract conditional type to retrieve the type based on the provided string:

interface test1 { type: 'test1' }

interface test2 { type: 'test2' }

type unType = test1 | test2;

function whichType<K extends unType['type']>(typeValue: K): Extract<unType, {type: K}> {
    return null!;
}

const tt1 = whichType('test1'); // test1
const tt2 = whichType('test2'); // test2

Creating a solution that works for any union involves using function currying due to TypeScript's lack of support for partial type parameter inference:

function whichType<T extends { type: string}>() {
    return function <K extends T['type']>(typeValue: K): Extract<T, {type: K}> {
        return null!;
    }
}

const tt1 = whichType<unType>()('test1'); // test1
const tt2 = whichType<unType>()('test2'); // test2

Answer №2

If you want to approach it from a type perspective and use literals when calling whichType, you can achieve this by utilizing function overloading:

interface test1 {
    type: 'test1'
}

interface test2 {
    type: 'test2'
}

type unType = test1 | test2;

function whichType(typeValue: 'test1'): test1;
function whichType(typeValue: 'test2'): test2;
function whichType(typeValue: string): unType {
    switch (typeValue) {
        case 'test1':
            return <test1>null;
        case 'test2':
            return <test2>null;
        default:
            throw new Error(`Unknown type ${typeValue}`);
    }
}

const tt1 = whichType('test1'); // tt1's type is test1
const tt2 = whichType('test2'); // tt2's type is test2

Check it out on the playground

As indicated in the code comment, you will still require runtime logic to handle it during execution.

If you wish to allow non-literal strings in calls to whichType, you would have to include another overload:

function whichType(typeValue: string): unType;

...and then address the challenge of working with an unknown type. :-|

[On the playground][2]

[2]: function whichType(typeValue: string): unType;

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

Create a dynamic function that adds a new property to every object in an array, generating unique values for

On my server, I have a paymentList JSON that includes date and time. Utilizing moment.js, I am attempting to create a new property called paymentTime to store the time data, but it seems to not update as expected. this.paymentList.forEach(element => ...

What is the process to verify a password?

Hey everyone! I've successfully implemented control forms in my login.component.ts for handling email and password input. Now, I want to add these controls to my register.component.ts as well. Specifically, how can I implement controls for the passwor ...

Guide on transferring the Token from the initial response request to the header of the second request, with the help of Axios in an Ionic React application (Making 2 Post Requests

I am trying to create a user account and save the partner's data simultaneously. The initial axios request is used to create the user and obtain a token in return. I need to pass this token as a header in the second request. Despite implementing &apos ...

Occasionally the CUSTOM_ELEMENTS_SCHEMA error may appear intermittently

After updating from Angular 8 to Angular 9, I encountered an error when running the application: error NG8002: Can't bind to 'text' since it isn't a known property of 'app-custom-message'. 1. If 'app-custom-message&a ...

Use the mat-autocomplete filter to emphasize partial string matches in the search results

Is there a way to achieve a filter using mat-autocomplete similar to the one shown in this example: trade input example I am looking to implement functionality where as users type in the trade they are searching for, filters are applied based on partial ...

Why does VSCode open a React app in Edge instead of Chrome?

Recently, I began a new project using the react-create-app template with typescript. However, when I run npm run dev, it unexpectedly opens in the Edge browser instead of Chrome. Does anyone know how to make it open in Chrome instead? ...

Establish a connection between a React variable and state management

In my codebase, I have an external module file named Task.ts. It contains the following: const taskList: Task[] = []; Class Task { ... } export { Task, taskList } The taskList is a list of Task objects that can be modified by the Task class. Now, i ...

Using Iframe for WooCommerce integration and implementing Facebook login within an Ionic application

I have created an Ionic application that includes an iframe from a Wordpress website. Here is the code snippet from my home.page.ts file: import { Component } from '@angular/core'; import { DomSanitizer } from "@angular/platform-browser"; @Com ...

The request to search for "aq" on localhost at port 8100 using Ionic 2 resulted in a 404 error, indicating that the

Trying to create a basic app that utilizes an http request, but facing challenges with cors in ionic 2. To begin with, modifications were made to the ionic.config.json { "name": "weatherapp", "app_id": "", "v2": true, "typescript": true, "prox ...

Different Approaches for Handling User Interactions in Angular Instead of Using the Deferred (Anti-?)Pattern

In the process of developing a game using Angular, I have implemented the following mechanics: An Angular service checks the game state and prompts a necessary user interaction. A mediator service creates this prompt and sends it to the relevant Angular c ...

Exploring Angular 10 Formly: How to Retrieve a Field's Value within a Personalized Formly Wrapper

Utilizing Angular 10, I have a formly-form with a select-field named session. This select field provides options from which to choose a dndSession. Each option holds key-value pairs within an object. I want to add a button next to the select-field that tr ...

Employing a one-time use variable that is asynchronously loaded via a React hook

Currently, I am exploring the functionalities of React's hooks, but I'm encountering a roadblock when it comes to integrating different use cases. The main goal is to create a hook called useNationsAsync that fetches a list of available nations ...

Trouble arises when trying to use add event listener on dynamically generated elements through (*ngFor)

Expanding the Accordion View Issue Whenever the section button is clicked, the event listener userSelection[i].addEventListener changes the id to 'open', thus expanding the accordion. This functionality works without any issues when not using t ...

What is the method in Angular 6 that allows Observable to retrieve data from an Array?

What is the method to retrieve data of an Array using Observable in Angular 6? ob: Observable<any> array = ['a','b','c'] this.ob.subscribe(data => console.log(data)); ...

The risk of a race condition could arise when working with nested switchMaps in ngr

I am currently working on an Angular 9 application that heavily relies on observables. In a specific component, I have the following requirements: Retrieve all companies to access certain information. Fetch all responses and link additional company detai ...

Testing react-native components using styled-components theme within react-native testing-library

I've hit a roadblock trying to pinpoint my mistake here. I've attempted various solutions without success. To illustrate the issue, I created a simple component to demonstrate what's going wrong. Below is my theme: export default const them ...

Unable to locate the 'NodeJS' namespace along with node types

I encountered an error in my web application: ERROR in node_modules/zone.js/dist/zone.js.d.ts:600:21 - error TS2503: Cannot find namespace 'NodeJS'. 600 declare var global: NodeJS.Global; Even after adding the types": ["node"] pr ...

Why is it necessary to include the spread operator before an array of objects?

Currently delving into Angular and stumbled upon a code snippet that seems a bit cryptic to me. The function I'm working with returns an array of objects as Observable<Product[]>: connect(): Observable<Product[]> { const dataMutati ...

Typescript Array does not adhere to correct data type

Why does the code below fail to transpile when pushing a new instance of class B into an array that is typed as only accepting instances of class A? class A {}; class B {}; const arr: A[] = []; arr.push(new B()); ...

Determining the output type by considering the presence of optional parameters

function customFunction<T>(defaultValue?: T) { return defaultValue; } const definitelyNullOrUndefined = customFunction<string>(); // type: string | undefined const definitelyStringType = customFunction<string>('foobar'); // ...