Retrieve a type from a Union by matching a string property

Looking at the following structure:

type Invitation =
  | {
      __typename?: 'ClientInvitation'
      email: string
      hash: string
      organizationName: string
    }
  | {
      __typename?: 'ExpertInvitation'
      email: string
      hash: string
      expertName: string
    }

is there a way to determine one of the types?

For instance:

type ClientInvitation = SomeTypeUtil['ClientInvitation']

would result in ClientInvitation having:

    {
      __typename?: 'ClientInvitation'
      email: string
      hash: string
      organizationName: string
    }

Answer №1

To simplify this process, you can utilize a mapped type with keys renamed as shown below:

type InvitationMap = { [T in Invitation as NonNullable<T['__typename']>]: T }

In this instance, we are iterating through the type T across the various members of union type within Invitation. For each member T, we aim to assign the property value as T, and set the property key to be a string literal type derived from the __typename property of T. This can be achieved by using T['__typename'] with indexed access types, albeit with a minor caveat. Since the __typename property is optional, the property type may include undefined (e.g., 'ClientInvitation' | undefined' or 'ExpertInvitation' | undefined'). To swiftly eliminate undefined, we can leverage the NonNullable<T> utility type.

Upon inspecting the IntelliSense quick info for the InvitationMap type:

/* type InvitationMap = {
    ClientInvitation: {
        __typename?: "ClientInvitation" | undefined;
        email: string;
        hash: string;
        organizationName: string;
    };
    ExpertInvitation: {
        __typename?: "ExpertInvitation" | undefined;
        email: string;
        hash: string;
        expertName: string;
    };
} */

With the defined InvitationMap, you can easily reference it with the desired key:

type ClientInvitation = InvitationMap['ClientInvitation'];
/* type ClientInvitation = {
    __typename?: "ClientInvitation" | undefined;
    email: string;
    hash: string;
    organizationName: string;
} */

Link to code on Playground

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

Setting character limits when defining string variables in TypeScript

Upon reviewing the documentation, it appears that there is no straightforward method to perform type checking for the minimum and maximum length of a string data type. However, is there a possible way to define a string data type using custom types in ord ...

What is the best way to depict object key replacements within a Typescript definition?

I currently have these types: type PossibleKeys = number | string | symbol; type ValueOf<T extends object> = T[keyof T]; type ReplaceKeys<T extends Record<PossibleKeys, any>, U extends Partial<Record<keyof T, PossibleKeys>> = ...

Windows drive letter casing error when using Yarn and NextJS

Today, I set up a fresh project using Yarn and NextJS on my Windows computer. When I try to start the project, I encounter an error stating that the casing is "invalid" for the project directory. The specific errors I am facing are: Invalid casing detecte ...

"Error message: TypeORM DataSource encounters a password issue with the client

Here is the content of my data-source.ts file: import {DataSource} from "typeorm"; import path from "path"; import {User} from "./entity/User"; import { config } from "dotenv"; config(); export const AppDataSource ...

Error encountered while bundling CDK Synth with Node.js function - Kindly ensure to update your lock file by running `npm install` before proceeding further

As I attempt to utilize AWS CDK for creating a Lambda function, I am facing a challenging error: "npm ERR! npm ci can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file ...

What is a way to merge all the letters from every console.log result together?

I'm encountering an issue - I've been attempting to retrieve a string that provides a link to the current user's profile picture. However, when I use console.log(), the output appears as follows: Console Output: https://i.sstatic.net/70W6Q ...

A versatile Material UI paper that adjusts its dimensions dynamically

Utilizing Material-UI's Paper component (https://mui.com/components/paper/), I've encountered a scenario where the content within the Paper element needs to be dynamic. <Paper className="modal" elevation={3}> ...Content </Paper ...

Using variables within the useEffect hook in ReactJS

I am currently working on a project using Reactjs with Nextjs. I am facing an issue where I need to retrieve the value of "Editor" and alert it inside the handleSubmit function. Can anyone help me with how to achieve this? Here is my code snippet, any as ...

Determining Refresh Status in Angular Application

Does Angular provide a method to determine if the browser has been refreshed? I need to verify whether the page has been refreshed or not, as I want to run a function only when the value is false. In my ngOnInit function, I have the following code: pageIs ...

GlobalsService is encountering an issue resolving all parameters: (?)

I am currently working on implementing a service to store globally used information. Initially, the stored data will only include details of the current user. import {Injectable} from '@angular/core'; import {UserService} from "../user/user.serv ...

execution of synchronized task does not finish

My approach to running Protractor tests in a headless mode using Xvfb may not be the most efficient, so let me outline my high-level requirement first. I am utilizing the angular2-seed and I aim to execute Protractor tests in a headless mode by incorporat ...

Failure to trigger the callback for mongoose.connection.once('open') event

Currently, I am in the process of setting up a custom Node server using Next.js. Although I'm utilizing Next.js this time around, it should not affect the outcome. In my previous applications, I always relied on mongoose.connection.once('open&ap ...

Is there a way to adjust the starting and ending points of a bezier curve in D3 by utilizing the link generator?

I'm currently working on developing a horizontal hierarchical tree Power BI custom visual using TypeScript and D3. I am utilizing d3's treeLayout for this purpose, and my task is to create a link generator that can plot bezier, step, and diagonal ...

Upgrade from using fetch to utilize await in order to achieve the same outcome

After transitioning a one-time fetch request code snippet to my API, I encountered the following: let response = await fetch(visitURL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization& ...

Guide to creating a function and exporting it to a component in react with the help of typescript

I have a ParentComponent where I need to integrate a function from a separate file and incorporate it into the ParentComponent. The structure of the ParentComponent is as follows: function ParentComponent() { const count = 5; // this value usually co ...

Receiving an error while passing properties to a React component: "Property 'firstName' is not found on type 'Readonly<{}>'."

As a beginner in React, I need some patience I'm attempting to create a simple component where users can input their first and last names, update the values, and see them displayed after clicking a button. However, I keep encountering TypeScript comp ...

Is there a way to programmatically add a timestamp to a form in Angular6?

Is there a way to automatically populate new forms with the current datetime value? this.editForm.patchValue({ id: chatRoom.id, creationDate: chatRoom.creationDate != null ? chatRoom.creationDate.format(DATE_TIME_FORMAT) : null, roo ...

Upon refreshing the page, the Vuex store getter displays [__ob__: Observer]

After each page refresh, my Vuex store getter returns [__ob__: Observer]. The version of Vue being used is 2.2.3 along with TypeScript. Initially, the data loads correctly from an external API, but when utilizing the getter, it fails and requires another ...

The selected image should change its border color, while clicking on another image within the same div should deselect the previous image

https://i.sstatic.net/jp2VF.png I could really use some assistance! I've been working on Angular8 and I came across an image that shows how all the div elements are being selected when clicking on an image. Instead of just removing the border effect f ...

Creating a component in Angular that utilizes multiple nested FormGroups

When attempting to nest multiple FormGroups, everything works smoothly if the template is not extracted into separate components. For instance, the following example functions as expected: Template <form [formGroup]="baseForm"> <div formGr ...