A safeguard for specific values in union types

In TypeScript, I have defined two types:

type PublicMethods = 'Time' | 'Assets' | 'AssetPairs';
type PrivateMethods = 'Balance' | 'TradeBalance';

I am looking to streamline the usage of the api function for both types, but with different behaviors for each. Here is what I have tried:

public api = (method: PublicMethods | PrivateMethods, params: any) => {

  // How can I implement a type guard here?
  if(method instanceof PublicMethods) { // 😱 This doesn't work!
    // ...
  }

}

I also attempted overloading the function:

public api(method: PublicMethods | PrivateMethods, params: any, callback: Function);

public api(method: PublicMethods, params: any, callback: Function) {
   // ...implementation
}

public api(method: PrivateMethods, params: any, callback: Function) {
   // ...implementation
}

Neither approach worked as expected. Any ideas on how to achieve this?

Answer â„–1

If you want to create a custom type guard, here's how you can do it:

const isPublicMethod = (value: any): value is PublicMethod => {
  return ['Time', 'Assets', 'AssetPairs'].includes(value);
};

You can then incorporate this type guard into your API integration function like this:

public api = (method: PublicMethods | PrivateMethods, params: any) => {
  if(isPublicMethod(method)) {
    ...
  }
}

Just a heads up! Make sure to update the PublicMethod type guard when making changes to the PublicMethod type in TypeScript.

For better management, consider using this alternative method:

const PUBLIC_METHODS = ['Time', 'Assets', 'AssetPairs'] as const;

type PublicMethod = typeof PUBLIC_METHODS[number];

const isPublicMethod = (value: any): value is PublicMethod => {
  return PUBLIC_METHODS.includes(value);
};

Answer â„–2

When defining types based on a constant array, you have the flexibility to use the name PublicMethods both as a type and a variable that references the union of strings and arrays.

const PublicMethods = ['Time', 'Assets', 'AssetPairs'] as const;
const PrivateMethods = ['Balance', 'TradeBalance'] as const;

type PublicMethods = typeof PublicMethods[number];
type PrivateMethods = typeof PrivateMethods[number];

By implementing a user-defined type guard using a type predicate, you can ensure that the value is narrowed down to PublicMethods, the type:

function isPublicMethod(value: string): value is PublicMethods {
    // An assertion is necessary to avoid an error stating that type 'string' is not assignable to types '"Time" | "Assets" | "AssetPairs"'
    return PublicMethods.includes(value as any);
}

This method allows you to specifically identify and narrow down values to the type PublicMethods by verifying if the array includes the specified value:

function doStuff(method: PrivateMethods | PublicMethods) {
    if (isPublicMethod(method)) {
        method
        // This now represents PublicMethods
    }
}

Feel free to experiment with this concept in the 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

Utilizing express-session in TypeScript: Incorporating user information into the session

Hey, I'm currently working on implementing express-session and connect-mongodb-session in my TypeScript Express/Node API. My goal is to use express-session to create a cookie for logged-in users and automatically persist that cookie to MongoDB. Howeve ...

In tsconfig.json, the compiler is not utilizing other tsconfig.json files when using the "extends"

I'm attempting to streamline my project by breaking up my tsconfig.json into separate files. I have one for the source files and another for the tests. However, when I utilize the extends field, it seems that only the base tsconfig.json is being utili ...

I'm curious, in TypeScript, how can I access a class variable from within a method

I've hit a roadblock and can't seem to figure it out. Despite scouring the forum and tirelessly searching on Google for hours, I'm unable to solve this issue! This is my first attempt at creating an app with Angular, and it's safe to sa ...

Enhancing menu item visibility with Typescript and Vue.js 3: A step-by-step guide

How can I dynamically highlight the active menu item in my menu? I believe that adding v-if(selected) and a function might be the way to go in the first template. <template> <MenuTreeView @selected='collapsedMenuSelected' :items=&apo ...

Lazy loading Google Analytics script in Angular: A step-by-step guide

Currently I am working with Angular 8 and I am interested in lazily loading my Google Analytics script. I came across some documentation that mentioned globally loading scripts lazily using the script array in angular.json: "scripts": [ "src/global-scri ...

Modify the [src] attribute of an image dynamically

I have a component that contains a list of records. export class HomeComponent implements OnInit { public wonders: WonderModel[] = []; constructor(private ms: ModelService){ ms.wonderService.getWonders(); this.wonders = ms.wonder ...

Checkbox selections persist when navigating between pages

I am currently working with Angular 9 and I have a list of checkboxes that need to default to true when displaying certain data. If one of these checkboxes is unchecked, it should trigger the display of specific information. The issue I am facing is that o ...

Is there a universal method to transform the four array values into an array of objects using JavaScript?

Looking to insert data from four array values into an array of objects in JavaScript? // Necessary input columnHeaders=['deviceName','Expected','Actual','Lost'] machine=['machine 1','machine 2&apo ...

Prisma: choose from numerous options in a many-to-many relationship with various criteria

I have a unique scenario with two tables, User and Post, that are connected through a custom many-to-many table: model User { id Int @id @default(autoincrement()) name String enabled Bool posts users_to_posts[ ...

A guide to setting initial values in Angular 2 using TypeScript

My Rank class includes attributes for "loses" and "wins" obtained from a web service. I need to calculate the "points" attribute based on these values. For example: for(int i = 0; i<loses; i++{ points += 1; } for(int i = 0; i<wins; i++{ point ...

Is it possible to assign an object literal to a typed variable in TypeScript? Can you also specify the typeof object literal?

Consider a scenario where you have the following type definition: type MyType = { A: number | string } If you try to assign a value like this, TypeScript will correctly flag it as an error: const myValue1: MyType = { A: 123, B: "Oh!", // This wil ...

Importing SCSS files dynamically with TypeScript

Recently, I utilized Create React App (CRA) to create a new project and then included node-sass in order to import SCSS files. An example: import "./App.scss"; Although this method works without any issues, I encountered a problem when trying t ...

Is there a way to position the label to the left side of the gauge?

Is there a way to position the zero number outside the gauge? I'm having trouble figuring out how to do it because the x & y options won't work since the plotLine's position keeps changing. The zero needs to move along with the plotLine and ...

Issue during Firebase production: emptyChildrenSingleton isn't recognized

In my nextjs project, I am using React v18.1.0 and Firebase Realtime Database for handling notifications. The notifications work fine in development mode but fail in the production environment. The errors I encountered are as follows: ReferenceError: empt ...

What is the best way to retrieve the value from a Material UI textfield after hitting the enter key

Having trouble retrieving input values with the provided code. Attempted using onKeyUp, onKeyDown, and onKeyPress, but none of them returned the value as desired. Typically, I would use the onChange property to get the value, but it triggers for every ne ...

Include type annotations for property value shorthand

MergedObject is a container that can store multiple MyClass instances as key-value pairs, where the key represents the variable name (e.g. Obj1) and the value is the corresponding MyClass instance. How can I define a type annotation for MergedObject? cla ...

How to Resolve a Typescript Promise Syntax Error?

I have been working on creating a login authorization system to secure certain routes in an angular application, but I keep encountering a TypeScript error in the auth-guard.service during compilation. Despite my efforts, I am unable to pinpoint the issue. ...

"Encountering a build failure in Next.js when using getStaticProps because a parameter is returning undefined

An unusual error has recently surfaced, causing our builds to fail, Located within the pages directory is a post/[id].tsx file that utilizes getStaticProps and getStaticPaths -- props export const getStaticProps: GetStaticProps = async ({ params }) => ...

Provide initial values to a custom TypeScript hook

As a new TypeScript user, I am trying to implement a hook called useForm to use in all forms. However, I am facing an issue with passing initial values using the code snippet below. Can someone help me troubleshoot this? interface IForm1 { name?: strin ...

When running ng build, the DefinitelyTyped package @types/async encounters issues

Previously, we built a website last year using the following versions: node v6.9.1 npm v3.10.8 angular-cli v1.0.0-beta.24 typescript v2.1.4 The application was successfully created by the previous developer. However, after setting up these versions and ...