Find the object in the array that has a name that is a combination of

I am facing an issue in implementing TypeScript validation for filtering an array. I have a specific array of actions and I want to filter out internal actions from it. Despite my efforts, I am unable to properly communicate to TypeScript that the filteredActions array should not contain internalAction anymore.

Below is my attempted solution:

type ActionName = 'replaceText' | 'replaceImage' | 'internalAction';

interface Action {
  name: ActionName
}
const INTERNAL_ACTIONS = ['internalAction'] as const;
type InternalActions = typeof INTERNAL_ACTIONS[number];

const actions: Action[] = [{
   name: 'replaceText'
}, {
   name: 'replaceImage'
}, {
   name: 'internalAction'
}];
const isInternalAction = (name: ActionName): name is Exclude<ActionName, InternalActions> => name in INTERNAL_SLIDE_ACTIONS;
const filteredActions = actions.filter((action) => !isInternalAction(action.name));
for (const action of filteredActions) {
  if (action.name === 'internalAction') {
    // TypeScript error expected here because internalAction shouldn't be present
  }
  if (action.name === 'replaceImage') {
    // No TypeScript error expected here
  }
}

Answer №1

The problem lies within the arrow function isInternalAction.

In TypeScript, to check if an element is present in an array, you should not use the in operator. Instead, consider using methods like includes, some, find, or indexOf.

To improve your code, consider a snippet like:

type ActionName = 'replaceText' | 'replaceImage' | 'internalAction';

interface Action {
  name: ActionName
}
const INTERNAL_ACTIONS: readonly ActionName[] = ['internalAction'] as const;
type InternalActions = typeof INTERNAL_ACTIONS[number];

const actions: Action[] = [{
  name: 'replaceText'
}, {
  name: 'replaceImage'
}, {
  name: 'internalAction'
}];

// Use includes to verify presence in the array
const isInternalAction = (name: ActionName): boolean => INTERNAL_ACTIONS.includes(name);
const filteredActions = actions.filter((action) => !isInternalAction(action.name));

console.log(filteredActions)

You can also test and run this code in a TypeScript playground here.

Answer №2

The key was using the filter method to rebind the action while excluding certain names:

const filteredActions = slide.actions.filter((action): action is Action & {
    name: Exclude<ActionName, InternalActions>
} => typeof INTERNAL_ACTIONS.find(i => i === action.name) === 'undefined');

This ensured that each action maintained the correct typings after filtering.

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

Silence in Angular NGRX Effects

I am currently utilizing ngrx Effects to send a http call to my server, but for some reason the effect is not triggered. My goal is to initiate the http call when the component loads. I have tried using store.dispatch in ngOnInit, however, nothing seems to ...

unable to locate the custom npm package within my service

There is a similar inquiry posted here: My custom NPM Package is not found, but unfortunately, the solution provided did not fix my issue. I am encountering an error stating: "Could not find a declaration file for module '@dc_microurb/common' ...

What is the proper syntax for defining an object property as a function?

Could someone help me find the specific location in the documentation where I can learn about the syntax of the line testMessage: (): string => {? Shouldn't it be more like testMessage: () => string;? Why are they not the same? export default { ...

Running into issues with TypeScript in conjunction with Redux-Form and React-Redux connect

My excitement for TypeScript grew until I encountered some frustrating incompatibilities between Redux-Form and React-Redux. I am aiming to wrap a component decorated with reduxForm using the connect decorator from react-redux—this method has always bee ...

The battle of environmental impact versus utility value in the realm of constants

Imagine having a collection of links that you want to organize in a separate file like this: export const SITE_LINKS = [ { text: 'About', path: '/about' }, { text: 'Projects', path: '/projects} ] You plan to utiliz ...

I can't figure out why I'm getting the error message "Uncaught ReferenceError: process is not defined

I have a react/typescript app and prior to updating vite, my code checked whether the environment was development or production with the following logic: function getEnvironment(): "production" | "development" { if (process.env.NODE_E ...

Supabase Authentication User Interface Error: Uncaught TypeError - Unable to access properties of null (specifically 'useState')

Concern Whenever I incorporate this Auth component into my login page, I encounter an issue. I am attempting to adhere to the guidelines provided in Supabase Auth with Next.js Pages Directory. If you suspect that this problem stems from a version discrepa ...

React - All subsequent variable declarations must be of the same type

Running webpack in my React application results in the following error message appearing 58 times across different variables: https://i.sstatic.net/uedR7.png Removing the @types directory did not resolve the issue and instead produced a new error message: ...

Why is it that the HttpClient constructor in Angular doesn't require parameters when instantiated through the constructor of another class, but does when instantiated via the 'new' keyword?

I am trying to create a static method for instantiating an object of a class, but I have encountered a problem. import { HttpClient } from '@angular/common/http'; export MyClass { // Case 1 public static init(): MyClass { return this(new ...

Issue: Unable to locate 'child_process' in Angular 5

I am a newcomer to Angular, and I have encountered a requirement in my project to retrieve the MAC address of the user's system. To achieve this, I performed an NPM installation as shown below: npm install --save macaddress Next, I added the follow ...

Is it possible to verify type equality in Typescript?

If the types do not match, I want to receive an error. Here is an example of an object: const ACTIVITY_ATTRIBUTES = { onsite: { id: "applied", .... }, online: { id: "applied_online", .... }, ... } as co ...

Performing an Axios POST request in a React Native and React app using JSON.stringify and Blob functionality

I am currently developing an application where I have encountered an issue when calling an API endpoint in react native. Interestingly, the web app (built with React) does not encounter any errors. Here is the code for the web app using React with TypeScri ...

Struggling with hashtags and ampersands in Angular when making an HTTP request

Dealing with Special Characters # and & in Angular's http.get() Request URL Take a look at my code first. Angular Service let versionsearch = "&"; let strweeksearch = "%23"; this.http.get(this.apiUrl + 'GetVersionInfo?vehicleVersion=' + v ...

How do I implement locking for an array of records to safely add and remove elements in a multi-thread

Looking to retrieve URL queries from the server intermittently and store them in an array of records. To manage memory efficiently, it is important to deallocate elements in the array correctly. This has to be done within a separate thread to ensure smoot ...

What is the best way to test a local variable in Angular 2 using karma and jasmine?

I've been working on writing a unit test with jasmine, but I've run into an issue when trying to test a local variable using jasmine. I have successfully tested a global variable in the past, but testing a local variable seems to be more challeng ...

Implementing the react-i18next withNamespaces feature in Ant Design forms

I'm a newcomer to i18next and TypeScript, and I'm trying to translate an antd form using withNamespaces. export default withNamespaces()(Form.create()(MyComponent)); Encountering the following error: Argument of type 'ComponentClass< ...

The issue with ng-select arises when the placeholder option is selected, as it incorrectly sends "NULL" instead of an empty string

When searching for inventory, users have the option to refine their search using various criteria. If a user does not select any options, ng-select interprets this as "NULL," which causes an issue because the server expects an empty string in the GET reque ...

Issue arising with data exchange between components using data service in Angular 5

Utilizing data service to share information between components has presented a challenge for me. References: Angular: Updating UI from child component to parent component Methods for Sharing Data Between Angular Components Despite attempting the logic o ...

Discover the Vehicle API hierarchy based on year, model, and make effortlessly with the help of MMPickerView in your iOS application

I switched from ccpickerview to MMPickerView, but now I am facing issues passing JSON data for vehicle make and model based on the selected year. While I am able to retrieve the year from jsonData, the app crashes when I try to pick the make of the vehicle ...

Does anybody have information on the Namespace 'global.Express' not having the 'Multer' member exported?

While attempting to set up an endpoint to send a zip file, I keep encountering the following error: ERROR in ./apps/api/src/app/ingestion/ingestion.controller.ts:46:35 TS2694: Namespace 'global.Express' has no exported member 'Multer'. ...