How can TypeScript limit the number of properties allowed to be passed as a function parameter?

Here is what I currently have:

export interface RegionNode {
    nodeSelected: boolean;
    nodeEditable: boolean;
    zone: Partial<Zone>;
    parent: RegionNode | null;
    children: RegionNode[];
}

Now, I am looking for a sleek solution to create a generic function that accomplishes this:

function setNodeAndChildrenProperty(node: RegionNode, property: keyof RegionNode, state: boolean): void {
    // @ts-ignore
    node[property] = state;
    for (const child of node.children) {
        setNodeAndChildrenProperty(child, property, state);
    };
}

One issue I faced was having to resort to using @ts-ignore because I am unsure how to limit the list of permitted properties to only "nodeSelected" and "nodeEditable", as well as encountering other challenges.

What would be an elegant solution to address this dilemma?

Answer â„–1

To achieve this, create a mapped type that will extract properties assignable to a specific type (such as boolean):

type PropertiesOfType<ObjType, PropType> = {
    [Key in keyof ObjType as ObjType[Key] extends PropType ? Key : never]: ObjType[Key];
};

The code within the [Key in ____] with the as clause filters out keys using never for properties that do not match the target property type. For example,

PropertiesOfType<RegionNode, boolean>
results in this type:

{
    nodeSelected: boolean;
    nodeEditable: boolean;
}

This type can then be utilized in your function to ensure TypeScript's understanding of assignment compatibility between node[property] and state:

function setNodeAndChildrenProperty(
    node: RegionNode,
    property: keyof PropertiesOfType<RegionNode, boolean>, // <====
    state: boolean
): void {
    node[property] = state;
    node.children.forEach((child) => {
        setNodeAndChildrenProperty(child, property, state);
    });
}

Playground link

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

Issues arising post transitioning to 14.0.0 from 13.0.0 version of ngx-masonry library leading to failed tests

Following the update to the latest stable version of the library ngx-masonry 14.0.0, our tests started failing. The release was just yesterday (24.10.2022) and you can find the changelog here: https://github.com/wynfred/ngx-masonry/blob/master/CHANGELOG.md ...

The error message "TypeError: router.back is not a function" indicates that

Testing out the back route navigation in next.js and encountering an error during the test: https://i.sstatic.net/O6Nax.png The function for going back: const router = useRouter(); const handleClick = useCallback(() => { if (router ...

How come the Angular8 form status registers as VALID even if the input fields are empty?

The following is the structure of the component: export class SchedulerComponent implements OnInit { schedulerForm : FormGroup; constructor(private fb: FormBuilder, private schedulerReportService: SchedulerReportService) { this. ...

ngOnInit unable to properly listen to event stream

I've been trying to solve a persistent issue without success. The problem involves the interaction between three key elements: the HeaderComponent, TabChangingService, and TabsComponent. Within the HeaderComponent, there are three buttons, each with a ...

Using Vue.js 3 and Bootstrap 5 to Create a Custom Reusable Modal Component for Programmatically Showing Content

Trying to develop a reusable Modal Component using Bootstrap 5, Vuejs 3, and composible API. I have managed to achieve partial functionality, Provided (Basic Bootstrap 5 modal with classes added based on the 'show' prop, and slots in the body a ...

Having difficulty transferring types to and from a custom module?

I'm currently faced with an issue while working on a typescript module within a larger monorepo. I am having difficulty importing types from one package into another via node modules. The types are located at ./types, and my package.json contains a ke ...

Why doesn't Typescript 5.0.3 throw an error for incompatible generic parameters in these types?

------------- Prompt and background (Not crucial for understanding the question)---------------- In my TypeScript application, I work with objects that have references to other objects. These references can be either filled or empty, as illustrated below: ...

The art of crafting informative error log messages in Protractor using TypeScript

I am currently utilizing Protractor, written in typescript, to conduct tests on a live website. I am seeking guidance on how to generate log messages when a Protractor test fails. Presently, the only feedback received is a simple YES/NO message, as shown b ...

The element 'PROGRAM_ID' is not recognized within the 'import @metaplex-foundation/mpl-token-metadata' type

I am currently in the process of creating a token within the Solana network, but I've encountered a particular issue. I have successfully installed @metaplex-foundation/mpl-token-metadata and integrated it into my code; however, an error is persisting ...

Is it possible for Angular's `HttpClient` to use complex property types in the `.get()` generics aside from just `string` or `number`?

After spending an entire day researching the topic, I've hit a dead end. All my efforts have only led me to discover one thing—omission. None of the information I've come across mentions whether you can utilize non-simple types (such as string ...

What is the method in Angular 6 that allows Observable to retrieve data from an Array?

What is the method to retrieve data of an Array using Observable in Angular 6? ob: Observable<any> array = ['a','b','c'] this.ob.subscribe(data => console.log(data)); ...

A guide to effectively utilizing a TypeScript cast in JSX/TSX components

When trying to cast TypeScript in a .tsx file, the compiler automatically interprets it as JSX. For example: (<HtmlInputElement> event.target).value You will receive an error message stating that: JSX element type 'HtmlInputElement' is ...

Steps for aligning the upper rectangular text in the center of the larger rectangular border

https://i.stack.imgur.com/7yr5V.png I was aware of a particular element in html that had text positioned in the upper left corner, but my knowledge didn't go beyond that. Should I be adjusting the translation on both the X and Y axes based on the par ...

Is there something I'm overlooking, or is this behavior unusual for an "if statement"?

I am facing an issue with returning a value from a function. It seems like a simple task - just looping through my HTMLElements and returning the one I need. This problem is new to me, and I have spent a considerable amount of time debugging the code and ...

To effectively manage the form, I must carefully monitor any modifications and update the SAVE button accordingly in an Angular application

Are you experiencing an issue with detecting any changes on a page, where there is some information displayed and even if no changes are present, the SAVE button remains active for clicking? ngOnInit(): void { this.createConfigForm() th ...

Transform the object into an array of JSON with specified keys

Here is a sample object: { labels: ["city A", "city B"], data: ["Abc", "Bcd"] }; I am looking to transform the above object into an array of JSON like this: [ { labels: "city A", data: "Abc" }, { labels: "city B", data: "Bcd" }, ]; ...

What is the best way to include a Generic type into a functional component's props that also extends a different interface for its props?

Explanation I am currently working on developing a dynamic input form using the FormProvider feature from react-hook-form. const formMethods = useForm<TSongFormData>(); return ( <FormProvider {...formMethods}> <SongInputForm /> ...

Customize the format of data labels in horizontal bar charts in NGX Charts

I am currently using ngx-charts, specifically the bar-horizontal module. My goal is to format the data labels and add a percentage symbol at the end. I attempted to use the [xAxisTickFormatting] property, but it seems that my values are located within the ...

No bugs appeared in Next.js

I am currently in the process of migrating a large create-react-app project to NextJS. To do this, I started a new Next project using create-next-app and am transferring all the files over manually. The main part of my page requires client-side rendering f ...

Enabling Event bus suggestions for Typescript: A step-by-step guide

Hello, I've encountered an issue while attempting to add types for the TinyEmitter library. Specifically, I need to define two methods. First: addEventListener(e: string, (...args: any[]) => void): void; Second: emit(e: string, ...args: any[]): vo ...