Tips for modifying TypeScript class types based on a parent class object property?

As part of a project, I have created two classes:

  • ParentClass
  • childrenClass which extends the ParentClass class

Displayed below is the code for my ParentClass:

interface ConfSetup<T extends boolean> {
  enabled: T;
  permissions: bigint[];
  location: string;
}

interface AssistanceInfo {
  name: string;
  description: string
  category: string;
  id: number;
}

interface ParentClassConfiguration<T extends boolean> {
  confData: ConfObj<T>;
  assistance: HelpObj;
}

type ParentClassParameters<T extends boolean> = AssistanceInfo & ConfObj<T>;

class ParentClass<T extends boolean> {
  config: ConfObj<T>;
  assist: HelpObj;

  constructor({ enabled, permissions, location, name, description, category, id }: ParentClassParameters<T>) {
    this.config = {
      enabled, permissions, location
    };
    this.assist = {
      name, description, category, id
    }
  }
}

Following that, in the ParentClass constructor, I set appropriate values to the class properties.

In the context of the childrenClass, I extend the ParentClass with necessary details. The goal is to modify the type of a parameter in the ChildrenClass class when the value of ParentClass.conf.enabled is true.

I attempted the following code (for the children class):

interface ChildConfigInterface<T extends ParentClass<any>> {
  isEnabled: () => boolean;
  name: string;
  description: string | (T["conf"]["enabled"] extends false ? undefined : never);
}

class ChildrenClass extends ParentClass<true>  {
  constructor() {
    super({
      enabled: true,
      permissions: [],
      location: '',
      name: '',
      description: '',
      category: '',
      id: 0
    });
  }

  operate(data: ChildConfigInterface<ChildrenClass>) {
    return data.description;
  }
}

So, in this scenario, if we set the ParentClass value to true, the type of data.description should be string. Conversely, if enabled is set to false, then the type of data.description will be string | undefined.

I hope this explanation clarifies the concept. For further understanding, please refer to the provided minimal reproducible example on TS playground. The operate method within the ChildrenClass should execute error-free, without adding any conditional statements or altering the method's return type.

Answer №1

It seems like achieving the exact behavior you're looking for may not be possible due to the dynamic nature of conf.enabled:

const foo = new childrenClass();
foo.run(data) // data.description should be a string
foo.conf.enabled = false; // Changing the type of `run()` is not feasible

One potential solution could involve omitting ChildrenType:

class childrenClass extends ParentClass implements ChildrenType<true> {
  constructor() {
    super({
      enabled: true
    });
  }

  public run(interaction: Omit<AChildrenParameterInterface, "isEnabled"> & { description: string }): any {
  }
}

Using generics might be an option, though it may not provide significant benefits in this scenario. To better address your requirements, additional details from your code would be helpful.

export interface ParentClassType<T extends boolean> {
  conf: ConfObj & {enabled: T};
  help: HelpObj;
}

interface ChildrenType<T extends boolean> extends ParentClassType<T> {
  run: (interaction: T extends true ?  (
    Omit<AChildrenParameterInterface, 'isEnabled'> &
    {
      description: string;
    }
    ) : AChildrenParameterInterface) => any;
}

class childrenClass implements ChildrenType<true> {
  constructor() {
    super({
      enabled: true
    });
  }

  public run(interaction: Omit<AChildrenParameterInterface, "isEnabled"> & { description: string }): any {
  }
}

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

"Enhancing User Experience: Implementing Internationalization and Nested Layouts in Next.js 13.x

In the midst of working on a cutting-edge Next.js 13 project that utilizes the new /app folder routing, I am delving into the realm of setting up internationalization. Within my project's structure, it is organized as follows: https://i.stack.imgur.c ...

When running on localhost, IE11 only shows a white screen while the other browsers function properly

I have recently completed a web-based project and successfully deployed it. The project is running on port 8080. Upon testing in Chrome, Safari, and Firefox, the project functions without any issues, and no errors are displayed in the console. However, wh ...

The evaluation of mongodb-memory-server is experiencing issues with either failing or timing out

While setting up mongodb-memory-server in my backend for testing purposes, I encountered some issues during test execution that require debugging. The problem arises when running a test that creates a MongoDB document within the service being tested, leadi ...

Ways to populate missing cells with a default hyphen symbol

Looking for a way to default empty cells in my primeng datatable to '-'. Consider the following data: [ { 'column': null }, { 'column': { 'name': 'A' } }, { 'column': { 'name': ...

In Angular, when using multiple-selection mode in mat selection, the Error Value should always be in the form of

**Everything is working fine except for one error in the console. How can I remove this error? Can anyone please help me? Save, Edit, and searching are working perfectly fine. ** public campaignCategoryFormGroup$: FormGroup = this.fb.group({ // 'c ...

Create a TypeScript function called toSafeArray that transforms any input into a properly formatted array

Is there a way to create a function that can transform any type into a safe array? toArray(null) // []: [] toArray(undefined) // []: [] toArray([]) // []: [] toArray({}) // [{}]: {}[] toArray(0) // [0]: number[] toArray('') // ['']: str ...

Object data is not being received by the defaultValue in React Hook Form

I am currently utilizing React Hook Form to facilitate the process of editing/updating data. I retrieve my data from zustand with a value type of any, and then proceed to save it as the defaultValue in React Hook Form. However, when attempting to acquire v ...

What is the best way to create a generic function parameter for a single property of an object?

I am trying to refactor a generic function into accepting parameters as a single object function test<T>(a: string, b: T, c: number) Instead, I want the function to receive an object like this: function test(params: {a: string; b: T, c: number}) I ...

Converting an array with objects to comma separated strings in javascript using (ionic , Angular , NodeJS , MongoDB)

Retrieving specific data from an API array: let passions = [ {_id: "60a1557f0b4f226732c4597c",name: "Netflix"}, {_id: "60a1557f0b4f226732c4597b",name: "Movies"} ] The desired output should be: ['60a1557f0b4f226 ...

The 'Content-Type' header cannot be defined for HTTP GET requests

I am currently working on setting up my GET requests to include the specific header: Content-Type: application/json Based on information from the documentation, I need to make the following adjustment: To customize these defaults, you can add or remov ...

NestJS does not recognize TypeORM .env configuration in production build

Currently, I am developing a NestJS application that interacts with a postgres database using TypeORM. During the development phase (npm run start:debug), everything functions perfectly. However, when I proceed to build the application with npm run build a ...

Tips for ensuring that npm only creates one instance of a dependency when it is being used by multiple projects

Struggling a bit here. I am diving into npm and configuration files for the first time. The current challenge involves setting up a vue project (though it might not be directly related to the issue) with typescript and then reusing its code and components. ...

I'm unable to modify the text within my child component - what's the reason behind this limitation?

I created a Single File Component to display something, here is the code <template> <el-link type="primary" @click="test()" >{{this.contentShow}}</el-link> </template> <script lang="ts"> imp ...

The detection of my query parameters is not working as expected

Creating an Angular application that dynamically loads a different login page based on the "groupId" set in the URL is my current challenge. The approach involves sending each client a unique URL containing a specific "groupId" parameter. A template is the ...

Is there a way to customize the default MuiCheckbox icon in theme.ts?

How can I customize the icon default prop for Mui checkbox? I followed the instructions provided here and used a snippet from the documentation: const BpIcon = styled('span')(({ theme }) => ({ borderRadius: 3, width: 16, height: 16, .. ...

Encountering a Typescript error with Next-Auth providers

I've been struggling to integrate Next-Auth with Typescript and an OAuth provider like Auth0. Despite following the documentation, I encountered a problem that persists even after watching numerous tutorials and mimicking their steps verbatim. Below i ...

After utilizing the d3-scale function to declare an object, my developer visual suddenly ceases to function

Upon completing a section of a Power BI tutorial, the developer encountered a visual that displayed nothing but a blank page (despite running correctly). Unable to pinpoint the issue, debugging was initiated. The following test code snippet for debugging w ...

Angular2's ngControl is unable to retrieve default values

I have been working on a form using Angular 2 (RC.3) and noticed that the `ngForm` directive is not recognizing default values set with the `value` attribute. // app.component.html <form (ngSubmit)="onSubmit(editForm.value)" #editForm="ngForm"> &l ...

Crafting a Retro Style

I have an interface called Product which includes properties such as name, and I want to track changes to these products using a separate interface called Change. A Change should include the original Product as well as all of its properties prefixed with t ...

Angular 2: The *ngFor directive is unable to locate a suitable differing framework

Below is the code for client.service.ts clients: Client[]; getClientList() { let headers = new Headers(); headers.append('Content-Type', 'application/json'); let authToken = localStorage.getItem('auth_token&apo ...