Ways to effectively demonstrate to TypeScript how the object's property is of a particular type in a dynamic manner

To view a live example of the code, visit: https://codesandbox.io/s/typescript-playground-pzl2s

I'm encountering an issue where the object contains two types of properties. At certain points, data is retrieved from the database with only the DRI child-property. Depending on the parent property, additional child-properties should be added.

The types for the parent properties and the entire object are as follows:

type BalanceModelSectionType = {
  DRI: {
    AI: number;
    AMDR: {
      from: number;
      to: number;
      [index: string]: number;
    };
    EAR: number;
    RDA: number;
    UL: number;
    unit: string;
    [index: string]: string | number | object;
  };
  quantity: number;
  converted: {
    quantity: number;
    unit: string;
  };
  percentage: number;
};

type BalanceModelContainerSectionType = {
  DRI: {
    AI: number;
    AMDR: {
      from: number;
      to: number;
      [index: string]: number;
    };
    EAR: number;
    RDA: number;
    UL: number;
    SC: number;
    [index: string]: number | object;
  };
  percentage: number;
  accomplished: number;
};

type BalanceModelType = {
  alanine: BalanceModelSectionType;
  arginine: BalanceModelContainerSectionType;
  // ... many others
  [index: string]: BalanceModelSectionType | BalanceModelContainerSectionType;
};

At one point, I receive the following object but it's missing some properties which are added in the forEach, resulting in a TypeScript error for missing properties:

const model: BalanceModelType = {
  alanine: {
    DRI: {
      AI: 0,
      AMDR: {
        from: 0,
        to: 0
      },
      EAR: 0,
      RDA: 0,
      UL: 0,
      unit: ``
    }
  },
  arginine: {
    DRI: {
      AI: 0,
      AMDR: {
        from: 0,
        to: 0
      },
      EAR: 0,
      RDA: 0,
      UL: 0,
      SC: 0
    }
  }
};

const defaultSectionValues = {
  quantity: 0,
  converted: {
    quantity: 0,
    unit: ``
  },
  percentage: 0
};
const progressSectionValues = {
  percentage: 0,
  accomplished: 0
};

Object.keys(model).forEach(sectionName => {
  const section = model[sectionName];

  /*
  How can I dynamically specify the type of a property within an object? */
  if (sectionName === `alanine`) {
    model[sectionName] = { DRI: section.DRI, ...progressSectionValues }; // Property 'SC' is missing in type
  } else {
    model[sectionName] = { DRI: section.DRI, ...defaultSectionValues }; // Property 'unit' is missing in type
  }
});

If you have suggestions on providing more accurate types for the object or handling types conditionally, your insights would be greatly appreciated.

Answer №1

To implement type checking, you could utilize a concept known as a type guard:

interface BaseType {
  ...
}

interface ExtendedType extends BaseType {
  quantity: number;
  ...
}

function isBaseType(obj: any): obj is BaseType {
  return obj.quantity === undefined;
}

function isExtendedType(obj: any): obj is ExtendedType {
  return obj.quantity !== undefined;
}

const getObject = (): BaseType | isExtendedType => {
  // Return the object dynamically as either BaseType or ExtendedType
}

const obj = getObject();
if (isBaseType(obj)) {
  // Object now has type BaseType
}
if (isExtendedType(obj)) {
  // Object now has type ExtendedType
}

Answer №2

If you encounter a situation where a field may be filled in at a later time, it indicates that the field could either be undefined or have a value. In Typescript, you can address this by defining the field as optional, like so:

interface SomeType {
   field?: string; // the field may contain a string or be undefined
   field2: string | undefined; // an alternative syntax for the same scenario
}

Therefore, make sure to mark all fields that are not always populated as potentially undefined.

Answer №3


define BalModelSecType = {
  DRI: {
    AI: integer;
    AMDR: {
      from: integer;
      to: integer;
      [index: string]: integer;
    };
    EAR: integer;
    RDA: integer;
    UL: integer;
    unit: string;
    [index: string]: string | integer | object;
  };
  amount?: integer;
  converted?: {
    quantity: integer;
    unit: string;
  };
  percentage?: integer;
};

Indicate nullable fields by using a question mark

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

The mat table is not displaying the values from the API despite receiving the correct array

I recently made the decision to dive into learning Angular, but I've encountered some difficulties. Specifically, I'm struggling to populate a table with values retrieved from an API using MatTable. Despite receiving the correct values from the A ...

Attempting to create a fresh string by substituting certain characters with different ones

Exploring TypeScript, I encountered a puzzle where I needed to substitute specific characters in a string with other characters. Essentially, replacing A with T, T with A, C with G, and G with C. The initial code snippet provided to me looked like this: e ...

Do interfaces in Typescript require nested properties to be mandatory?

My interface contains a nested object: export interface Person { PersonWrapper: { name: string; address: string email?: string; } } When attempting to create an object from this interface, it appears that name is not mandat ...

Encountering the following error message: "Received error: `../node_modules/electron/index.js:1:0 Module not found: Can't resolve 'fs'` while integrating next.js with electron template."

I am utilizing the electron template with next.js, and I am trying to import ipcRenderer in my pages/index.tsx file. Below is the crucial code snippet: ... import { ipcRenderer } from 'electron'; function Home() { useEffect(() => { ip ...

I need to find a way to dynamically filter a Json object, taking into account that my filter condition may vary. The number of possible scenarios

I need to dynamically filter my data based on changing conditions. For example, I want to call a method on the <select (change)="filterData($event.target.value,'jobStatusId')" >, but the condition to filter by can be dynamic, such ...

Select specific values from a JSON object based on the keys defined in a TypeScript type

I am working with the following content structure: interface User { email: string; name: string; } ...and have created a react component as shown below: const MyComponent = <Values extends object>({ values }: { values: Values }) => { consol ...

What are the best practices for implementing MapLabel in an Angular project?

I need help displaying text on top of multiple polygons on a map. I've heard that Map Label can help with this, but I'm having trouble implementing it and can't find any NPM resources. Here is the Stack Blitz URL for reference: https://stac ...

"What are the benefits of utilizing Dependency Injection tokens within Angular 4 and when is the ideal time to implement

I have been exploring the concept of using InjectionToken for injecting environment variables (plain objects) into a service. I find myself puzzled as to the reasons and methods for incorporating tokens in Dependency Injection. Despite my efforts to resear ...

Guide on incorporating a YouTube iframe in React with Typescript

It appears that Typescript is posing some challenges for me in this scenario. Here's the code snippet I am trying to include: <iframe width="560" height="315" src="https://www.youtube.com/embed/BLAH?showinfo=0" frameBorder="0" ...

React 16 exhibiting unexpected behavior with class names

I am trying to implement the classnames object into my input field within a react 16 project, completely independent of the webpack tool. const fieldClassName = classnames( formControlStyles.field, 'form-control' ) The 'form-control& ...

The "ng2-CKEditor" package is experiencing compatibility issues with TypeScript in Angular 2

Currently, I am in the process of setting up CKEditor in my angular2 application. My backend platform is node.js and for this purpose, I am utilizing the ng2-CKEditor npm module. Below, you can find snippets from respective files. index.html:: <html& ...

Leverage Component class variables within the Component hosting environment

Is there a way to utilize a class variable within the @Component declaration? Here is the method I am aiming for: @Component({ selector: "whatever", host: { "[class]":"className" } }) export class MyComponent { @Input() className: ...

Encountering an undefined property error when trying to access 'userService' while implementing an async validator in Angular 12

For the past few days, I've been struggling to implement async validation with no success from various tutorials and solutions! Service code- getUserIdToCheckDuplicate(userId:any):Observable<any>{ const url = ``; //url goes here return ...

Having difficulty locating the correct TypeScript interface for executing GraphQL queries in a React application using Apollo Client

In this React component code snippet, a table is returned with each row containing data fetched from a backend API using GraphQL. While the data is successfully fetched, there seems to be an issue in defining the correct interface for handling the data ret ...

Invoke the API when the value of a property in the SPFX property pane is modified

Here's a question that might sound silly, but I'll ask anyway. I have a dropdown field in my Property pane that is filled with all the lists from the current site. It's working fine. When I change the dropdown selection, it populates a pro ...

Test the HTML element using ngIf async call in Angular 2 with Jasmine unit testing

As I work on writing unit tests for an HTML div with a condition using *ngIf, I come across a specific scenario. <div *ngIf="clientSearchResults$ | async as searchResults" class = 'fgf' #datalist id="mydata" > <app-client-list id=" ...

How does Typescript's dynamic tuple typing tool display all available options in Autocompletion/Intellisense?

Being new to TypeScript, I am facing an issue that I am unsure how to resolve. I want to generate a list of tuples from a list of components. Each tuple should consist of the component's name (keyof MyComponents) and its attributes. (Refer to the co ...

Why does `react/require-default-props` still display an error even when a default prop value has been set?

This inquiry pertains to the guideline require-default-props. Here is the code snippet in question: function MyComponent({ blubb = 'my default', }: { blubb?: string, }) { // blubb defaults to 'my default' }; Eslint is flagging a ...

Attempting to establish a connection with MongoDB through Realm

Exploring Realm and MongoDB for the first time has been an interesting journey for me. I began by following a helpful tutorial as a starting point for my project. Here is the link to my project structure on CodeSandbox The folder structure includes: src ...

Updating tooltip text for checkbox dynamically in Angular 6

Can anyone help me with this code? I am trying to display different text in a tooltip based on whether a checkbox is active or not. For example, I want it to show "active" when the checkbox is active and "disactive" when it's inactive. Any suggestions ...