Is it possible to determine in Typescript whether a union type MAY include a subset of values?

I'm currently working on a function parameter that can accept any type within a union that includes a specified subset.

For instance:

type One = { a: "one"; b: 1 };
type Two = { a: "two"; b: 2 };

type U = One | Two;

// `CouldContain` is a wrapper indicating potential inclusion of `Two`
function test(param: CouldContain<Two>) {}

With this setup, the following examples would be valid:

const pass: U = { a: "one", b: 1 };

test(pass); // `U` contains `Two` 

As well as:

type Z = { } | Two

const pass: Z = { };
test(pass); // `Z` contains `Two`

However, scenarios like these would not work:

const fail = { a: "three", b: 3}

test(fail); // Not recognized as `Two`

And neither would:

const fail = { };

test(fail); // Although part of `Z` which includes `Two`, it fails to infer as `Z`

The specific use I have in mind involves dynamically determining if GraphQL data types may contain a particular union type.

Answer №1

That's quite an interesting question. Let me share my approach.

type CouldContain<T, U> = Extract<T, U> extends never ? never : T

function test<T>(param: CouldContain<T, Two>) {}

This method involves utilizing the argument param to deduce the generic type T and employing a conditional type to validate whether Two belongs to T.

One crucial point to remember when using this type:

type U = One | Two;
const pass: U = { a: "one", b: 1 } as U;
test(pass); // ok

type Z = { } | Two
const pass2: Z = { } as Z;
test(pass2); // ok

const fail = { a: "three", b: 3}
test(fail); // fails

const fail2 = { };
test(fail2) // fails

The use of type assertions as U and as Z is necessary for this technique to function correctly. Otherwise, the compiler may alter the types slightly by attaching "invisible" data based on literal types to pass and pass2. By adding type assertions, you prevent the compiler from making these adjustments, ensuring that Two remains part of their union.


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

Angular 5 Event Emitter and Output fail to trigger parent function

I've exhaustively researched and attempted all available options to no avail. Specifically, I have a button designed to switch between light and dark modes by toggling a boolean value passed to the parent component to alter the background color of the ...

Type error arises when attempting to map from JSON to TypeScript

I am currently working on mapping a list of .Net objects to my Angular frontend using Web Api 2. Depending on the circumstances, these objects and their properties may be an Employment reference, Assignment reference, or an Assignment organization unit ref ...

Tips for creating an HTTP only cookie in NestJS

Currently, I am in the process of incorporating JWT authorization with both an accessToken and refreshToken. The requirement is to store these tokens in HTTP-only cookies. Despite attempting this code snippet, I have encountered an issue where the cookies ...

When all observables have finished, CombineLatest will only execute one time

I've encountered a problem that requires me to use a combination of 3 route observables to open a modal. Here is the logic in my code: combineLatest([obs1, obs2, obs3]) .subscribe(([s1, s2, s3]: any) => { openModal(); }); The issu ...

What could be causing my mdx files to not display basic markdown elements such as lists and headings? (Next.js, mdx-bundler)

Trying to implement Kent C Dodds mdx-bundler with the Next.js typescript blog starter example is proving challenging. While it successfully renders JSX and certain markdown elements, basic markdown syntax like lists and paragraph spacing seem to be malfunc ...

Issue with Next.js: Router.push not causing page to refresh

I'm currently developing a next.js page called /page/data/[dataId] (this page is accessed when a user clicks on a link from the page /page/data, where I fetch the list of items through an API). When a user clicks on a button, I make an API call to de ...

Throw TypeError: The `pipe` property of `ngrx/store` is undefined during testing

Here is the code snippet from my TypeScript file: this.store.pipe(select(subscribe.getRegCategories)).pipe(takeUntil(this.ngUnsubscribe)).subscribe(data => { if (data && data.length) { this.allRegCategories = data; ...

After updating the state in a Reducer with Redux Toolkit, make sure to utilize a

Issue: Seeking efficient code writing methods. Here is a detailed example of my Redux Toolkit slice below: import { createSlice } from '@reduxjs/toolkit'; import { setCookie } from '../../utils/storageHandler'; const initialState = { ...

What is the most effective way to add cookies to the response object in a NestJS GraphQL application?

How can I save cookies in the response object of a NestJS GraphQL application? Here is the relevant code snippet: app.module.ts: GraphQLModule.forRoot<ApolloDriverConfig>({ autoSchemaFile: true, driver: ApolloDriver, cors: { ...

Angular 8: Implementing functionality for the Parent Component to detect when the User clicks outside of the Child Component Textbox

I am working on a scenario where I have a Parent Component and a Child Component containing a Formbuilder and a ZipCode textbox. Is there a way to notify the Parent Component when the user clicks out of the Child Component Textbox? I need to trigger some ...

Issue with Props Type Check not functioning as expected in Typescript with React

I am utilizing Typescript within my React application. I aim to rigorously verify the type of props being passed to my components and trigger an error if it does not match. import React from "react"; import styles from "./ServiceDetailCard.css"; type Ser ...

Tips for updating the class of the body in an Angular 2 and Typescript project

When it comes to managing different classes for the login page versus other pages in an application, there is a need to change the body element's class once the user has logged in. Here is how I am attempting to achieve this: index.html <body [ng ...

What is the process for eliminating the perplexing "default" attribute that has been inserted into JSON?

I recently came across the jsondata.json file: { "name": "John", "age": 30, "car": "ferrari" } Located in the same directory is a typescript file called main.ts where I simply output the json data using console.log import * as j from '. ...

The type 'Node' does not have the required attributes

Could anyone shed some light on what might be causing the issue described below? Your insights are greatly appreciated. The problem lies within the line of code: clone = thead.cloneNode(true); The error message reads: 'Type 'Node' is missin ...

Is it possible for me to dynamically alter the innerHTML of an input element using

I am working on a small Angular application. One of my components uses innerHTML to display content. <div [innerHTML]="serviceShared.currentMood"></div> However, when I change the value of serviceShared.currentMood in the main component, noth ...

What is the proper way to specify a generic type as a parameter in TypeScript?

I have devised a basic Form class using TypeScript: class Form<FormData> { protected data: FormData; constructor(data: FormData) { this.data = data; } } To ensure the form receives specific data upon instantiation, I included a ...

Validate certain elements within a form group in a wizard

Within my 2-step wizard, there is a form group in the first step. When the next page button is clicked on the first step, I want to validate the elements in that form group. My questions are: 1 - Would it be more effective to use 2 separate forms in each ...

Getting around using Material-UI Icons

Is it possible to utilize a Material-UI Icon for navigation using React Router Dom? I attempted the following approach without success: <NavigateBeforeIcon path="/vehicles"></NavigateBeforeIcon> With buttons, I am able to use component={Link ...

Angular's array filter functionality allows you to narrow down an

I am working with an Array and aiming to filter it based on multiple criteria: primasSalud = [ { nombre: 'one', internacional: true, nacional: false, nacionalSinReembolso: false, nacionalClinicasAcotadas: false ...

Ways to mandate a field to only be of type object in TypeScript

I need to design a type that includes one mandatory property and allows for any additional properties. For instance, I require all objects to have an _id property of type string. {_id: "123"} // This will meet the criteria {a: 1} // This will not work as i ...