What is a way to construct an object without resorting to casts or manually declaring variables for each field?

Click here for a hands-on example. Take a look at the code snippet below:

export type BigType = {
  foo: number;  
  bar?: number;
  baz: number;
  qux?: string[];
};

function BuildBigType(params: string[]) {
    // Here's what I'd like to do:
    const endResult: BigType = {};

    //some logic for getting foo
    endResult.foo = 5;

    //some logic for getting bar
    endResult.bar = undefined;

    //...

    return endResult;
}

The issue lies in the fact that {} doesn't conform to the structure of BigType. Two potential solutions come to mind:

  1. Type cast endResult to any and proceed with assigning the fields as demonstrated in the example.

  2. Declare local variables for each field in BigType, then assign them accordingly at the end of the function. For example:

      //...
      return {foo, bar, baz, qux};
    }
    

Are there any alternative approaches worth considering?

Answer β„–1

Finding a completely elegant solution may be challenging. My suggestion would be to go with option 2., as type inferences tend to work well when used together, and you can wait until the end to assemble the full type when you return. To further solidify this, you can explicitly set the return type of your function to avoid any potential errors.

function BuildBigType(params: string[]): BigType {
    //logic for obtaining foo
    const foo = 5;

    //logic for obtaining bar
    const bar = undefined;

    //...

    return {foo, bar, baz, qux};
}

Answer β„–2

If you're searching for a way to implement lazy object initialization in TypeScript, you may be interested to know that it is not directly supported. You can check out the open feature request microsoft/TypeScript#28503 and show your support by giving it a thumbs up.


One way to modify your code to avoid errors without resorting to using the potentially unsafe `any` type is to utilize a type assertion when declaring the variable. This would look like:

function BuildBigTypeAssert(params: string[]) {
  const endResult = {} as BigType;
  endResult.foo = 5;
  endResult.bar = undefined;
  return endResult; // no errors, but be cautious
}

While this approach is acceptable, keep in mind that the compiler won't catch an error if you forget to initialize a property, as shown with the missing `baz`. Another option is to create an assertion function to simulate lazy initialization:

function setProp<T extends object, K extends PropertyKey, V>(
  obj: T, key: K, val: V
): asserts obj is T & { [P in K]: V } {
  (obj as any)[key] = val;
}

The `setProp()` function allows for dynamic property assignments, providing a safer way to extend object types. Here is an example of how to use it in your code:

function BuildBigType(params: string[]): BigType {
  const endResult = {};
  setProp(endResult, "foo", 5);
  setProp(endResult, "bar", undefined);
  setProp(endResult, "baz", 123);
  return endResult; // no issues
}

By using `setProp()`, you ensure proper type checking and extend object types safely. If a property is forgotten, the compiler will raise an error as demonstrated in the `BuildBigTypeError` function.


Check out this Playground link with the code

Answer β„–3

To construct this entity, you can follow a two-step process. Initially, create a mandatory field entity. Subsequently, establish endResult: BigType and input values for optional fields.

export function ConstructBigType(parameters: string[]): BigType {
  // Create mandatory fields first
  const mandatoryFields = { foo: null, baz: null };
  mandatoryFields.foo = 5;
  mandatoryFields.baz = 10;

  const endResult: BigType = { ...mandatoryFields };
 
  // Establish optional fields
  endResult.bar = undefined;

  return endResult;
}

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

Error encountered in Angular: Trying to assign a value to an empty string array results in the error message "Type (string | undefined)[] is not assignable to

Struggling with an issue in my Angular App - trying to assign a value to an empty array Current environment: node 12.18.4 npm 6.14.8 Here's my typescript.ts code snippet: import { Injectable } from "@angular/core"; import { Product } from ...

Using `useState` within a `while` loop can result in

I'm working on creating a Blackjack game using React. In the game, a bot starts with 2 cards. When the user stands and the bot's card value is less than 17, it should draw an additional card. However, this leads to an infinite loop in my code: ...

The compiler option 'esnext.array' does not provide support for utilizing the Array.prototype.flat() method

I'm facing an issue with getting my Angular 2 app to compile while using experimental JavaScript array features like the flat() method. To enable these features, I added the esnext.array option in the tsconfig.json file, so the lib section now includ ...

Compare the values of properties in an array with those in a separate array to filter in Angular/TypeScript

There are two arrays at my disposal. //1st array tasks.push({ ID: 1, Address: "---", Latitude: 312313, Longitude: 21312 }); tasks.push({ ID: 3, Address: "---", Latitude: 312313, Longitude: 21312 }); //2nd array agentTasks.push({ID:2,AgentID: 2,TaskID:1}); ...

When transitioning from component to page, the HTTP request fails to execute

I have created a dashboard with a component called userInfo on the homepage. This component maps through all users and displays their information. Each user has a display button next to them, which leads to the userDisplay page where the selected user&apos ...

I am configuring Jest in my Vite and TypeScript-powered React project

I am having trouble with the relative path of the file I imported in App.test.tsx. It keeps showing me this error message: Cannot find module '@/components/items/card.tsx' from 'src/__tests__/App.test.tsx' Below is the code snippet: // ...

Identified the category

How can I retrieve the default option from a list of options? type export type Unpacked<T> = T extends Array<infer U> ? U : T; interface getDefaultValue?: <T extends Option[]>(options: T) => Unpacked<T>; Example const options = ...

It’s not possible for Typescript to reach an exported function in a different module

Having trouble referencing and using exported methods from another module. I keep getting an error that says 'There is no exported member in SecondModule'. module FirstModule{ export class someClass{ constructor(method: SecondModule ...

Most Effective Approach for Handling Multiple Fetch Requests Concurrently using Async-Await in TypeScript?

I am currently exploring the idea of making multiple API calls simultaneously by utilizing multiple fetch requests within an await Promise.all block, as shown below: const responseData = await Promise.all([ fetch( DASHBOARDS_API + "getGoal ...

Leveraging the power of the map function to manipulate data retrieved

I am working on a nextjs app that uses typescript and a Strapi backend with graphql. My goal is to fetch the graphql data from strapi and display it in the react app, specifically a list of font names. In my react code, I have a query that works in the p ...

A guide to adding a delay in the RxJS retry function

I am currently implementing the retry function with a delay in my code. My expectation is that the function will be called after a 1000ms delay, but for some reason it's not happening. Can anyone help me identify the error here? When I check the conso ...

Adding data-attributes to a Checkbox component using inputProps in React

Utilizing Fabric components in React + Typescript has been a breeze for me. I have been able to easily add custom attributes like data-id to the Checkbox component, as documented here: https://developer.microsoft.com/en-us/fabric#/components/checkbox Howe ...

Fetching Unicode block specials using axios in getStaticProps with Next.js

Click here to view the code and data results My attempt using the fetch method was successful, but I encountered issues when trying to use 'axios' ...

Methods to acquire the 'this' type in TypeScript

class A { method : this = () => this; } My goal is for this to represent the current class when used as a return type, specifically a subclass of A. Therefore, the method should only return values of the same type as the class (not limited to just ...

Swap out the default URL in components with the global constant

Could anyone offer some assistance with this task I have at hand: Let's imagine we have a global constant 'env' that I need to use to replace template URLs in components during build time. Each component has a default template URL, but for ...

The compilation of TypeScript extending DataType can sometimes result in errors

I have written a custom extension in my extensions/date.ts file which adds a method to the Date interface: interface Date { addDays: (days: number) => Date } Date.prototype.addDays = function(days: number): Date { if (!days) return this; let dat ...

Enhancing JSON data: Transforming basic JSON structure into more complex format

I am currently working on a typescript file that is receiving a JSON response from an external API. I am in need of assistance to convert the received JSON into a different format. Could someone please help me with this JSON conversion task? Sample JSON d ...

Passing a variable from the second child component to its parent using Angular

Need help with passing variables between two child components Parent Component: deposit.component.html <div> <app-new-or-update-deposit [(isOpenedModal)]="isOpenedModal"></app-new-or-update-deposit> </div> Deposit Component ...

Leverage TypeScript AngularJS directive's controller as well as other inherited controllers within the directive's link function

I am currently developing an AngularJS directive in TypeScript for form validation. I am trying to understand how to utilize the directive's controller and inherit the form controller within the directive's link function. Thank you in advance! ...

The argument passed cannot be assigned to the parameter required

Currently, I am in the process of transitioning an existing React project from JavaScript to TypeScript. One function in particular that I am working on is shown below: const isSad = async (value: string) => { return await fetch(process.env.REACT_AP ...