Guidelines for defining an Interface based on the value of another argument

Imagine a scenario where...

interface Group {
    name: string
    isPublic: boolean
}

interface User {
    id: string
    age: number
}

type EntityType = 'group' | 'user'

function doTask(type: EntityType, entity: Group | User): boolean {
    if (type === 'group') {
        return entity.isPublic
    }

    if (type === 'user') {
        return entity.age > 18
    }

}

I am seeking a way to specify that when the first argument is group, the entity should conform to the Group interface... It seems like Generics might be the solution, but I am struggling with the syntax.

How can I express "When type is value X then entity follows interface Y"?

Thanks in advance!

Edit: Changed to a Minimal Reproducible Example.

Answer №1

To inform TypeScript of the relationship between the two parameters, you'll need to establish a connection. Currently, your code only consists of two unions that are unrelated to each other.

One approach to create a correlation is by using a discriminated union of tuples, where the first element serves as the discriminator. Subsequently, you can destructure the tuple in the parameter list:

function handleData(...[type, entity]: ["group", Group] | ["user", User]) {

This method works well, but what if there are more than two options? You can succinctly express this tuple union as a map of strings to their corresponding interfaces:

interface EntityMap {
    group: Group;
    user: User;
}

type EntityType = keyof EntityMap; // define EntityType as a key of the map instead

You can iterate over each entity type and retrieve the respective interface type from the map:

function handleData(...[type, entity]: { [K in EntityType]: [K, EntityMap[K]] }[EntityType]) {

This yields the same type as before, enabling you to effortlessly expand the union with additional members if needed:

https://i.sstatic.net/VS1Rp.png

If readability concerns arise, you can abstract this into its own type alias:

type DataHandler = { [K in EntityType]: [K, EntityMap[K]] }[EntityType];

function handleData(...[type, entity]: DataHandler) {

Testing ground

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

Locate and refine the pipeline for converting all elements of an array into JSON format using Angular 2

I am currently working on implementing a search functionality using a custom pipe in Angular. The goal is to be able to search through all strings or columns in a received JSON or array of objects and update the table accordingly. Here is the code snippet ...

Is it possible for lodash's omit function to return a specific type instead of just a partial type?

Within the following code snippet: import omit from "lodash/fp/omit"; type EnhancerProps = { serializedSvg: string; svgSourceId: string; containerId: string; }; const rest = omit(["serializedSvg", "containerId"])(props); The variable 'rest&a ...

Working with Angular 4 and Typescript: Transforming JSON data with json2typescript key mapping

Apologies for the confusion in my previous explanation. Let me clarify my question: In my Angular 4 application, I am using json2typescript to handle JSON to object conversion. However, I am facing an issue where the class structure I have defined does no ...

unrecognized compiler flag 'noImplicitOverride'

Encountering an issue in my Angular 13 app with Typescript 4.5.2. The tsconfig.json file is causing trouble as setting "noImplicitOverride" to true results in an error message saying 'Unknown compiler option 'noImplicitOverride'.ts ...

Ensure Angular Reactive Forms do not include empty fields when submitting the form

Is there a way to retrieve only the fields with values entered by the user from a form and exclude empty fields in the resulting JSON object? Currently, the JSON object still includes empty quotation marks for empty inputs. Thank you! Current: { "user ...

What is causing this error/bug to show up in Angular?

I encountered an error while working on my Angular project that incorporates both front-end and back-end development with Python Flask. Even though the page updates correctly, a database-related error is being displayed in the console. Below are the snippe ...

Utilizing Typescript to extract type information from both keys and values of an object

I have a unique challenge of mapping two sets of string values from one constant object to another. The goal is to generate two distinct types: one for keys and one for values. const KeyToVal = { MyKey1: 'myValue1', MyKey2: 'myValue ...

TypeScript(error:2532): object may be undefined despite null or undefined check

Currently, I am developing a Discord-bot using TypeScript which includes a command to retrieve information from an airport. To do this, users only need to provide the 4-character ICAO code that identifies the specific airport. However, due to potential use ...

Identify numbers and words within a sentence and store them in an array

Looking to split a string into an array based on type, extracting numbers and floats. The current code is able to extract some values but not complete. var arr = "this is a string 5.86 x10‘9/l 1.90 7.00" .match(/\d+\.\d+|\d+&bsol ...

The service method call does not occur synchronously

In my OrderServer class, I am utilizing an OrderService to connect to a database and retrieve data every minute. The communication with the web app is handled through SocketIO. Here is a snippet of the code: export class OrderServer { // some required fie ...

What are the steps to incorporating the pick function in TypeScript?

The TypeScript documentation mentions a pick function that is declared but not implemented. In an attempt to create a simplified version, I wrote the following: function pick<T, K extends keyof T>(obj: T, key: K): Pick<T, K> { return { [key]: ...

Displaying Firebase data using Angularfire2 5.0 on an Ionic template

Hey everyone, I've been encountering a problem while trying to use angularfire2 v 5.0. I was comfortable using v 4.0 before, but now that I'm transitioning to v 5.0, I'm facing some issues. Does anyone know how I can display real-time data ...

Tips for effectively typing a collection of React wrappers in TypeScript

I encountered a situation in my team's application where we need the ability to dynamically compose component wrappers (HOCs) without prior knowledge of all the wrapper interfaces. This is mostly needed for swapping out context providers when renderin ...

Angular 2 Issue: Error Message "Cannot bind to 'ngModel'" arises after FormsModule is added to app.module

I've been struggling with the data binding aspect of this tutorial for over a day now. Here's the link to the tutorial: https://angular.io/docs/ts/latest/tutorial/toh-pt1.html The error I keep encountering is: Unhandled Promise rejection: Tem ...

Even when I try to access the properties of the arguments object, it remains empty and has a zero

Why is the arguments object showing a length of zero when I pass parameters to the function, even though I can still access its properties? I am referring to the arguments object that is implemented by all JavaScript functions, allowing you to access the f ...

Hold off until the observable has finished

map((tasks): any => { return tasks.map(task => ({ ...task, status: this.getStatus(task.owner, task.delegationState, task.assignee, task.id), })); }); I utilize the getStatus method within the map() operator from rxjs. getStatus( ow ...

Guide on uploading multiple images in react using Next.js

I am currently facing a challenge with uploading multiple images in React (nextjs) using the <input onChange={onChange} type='file' name='file' multiple/>. I have spent hours searching online for a solution but have not been succe ...

Error: Callstack Overflow encountered in TypeScript application

Here is the code snippet that triggers a Callstack Size Exceeded Error: declare var createjs:any; import {Animation} from '../animation'; import {Events} from 'ionic-angular'; import { Inject } from '@angular/core'; exp ...

What might be causing my action function to be triggered during the rendering process?

While working on creating a basic card view in material UI, I encountered an issue where the functions for adding and deleting items seem to be triggered multiple times upon rendering. I am aware that a common reason for this could be using action={myFunc ...

Having trouble with JavaScript's Date.getUTCMilliSeconds() function?

I have a straightforward question for you. Take a look at this Angular App and try to create a new date, then print the number of UTC milliseconds of that date in the console. Can you figure out why it is returning zero? ...