Create object properties as optional, declare them afterwards, and access them without needing to verify

I'm wondering if there's a way to work around type definitions. Let me provide an example to clarify my question.

Suppose I want to define a type that consists of a large object containing multiple objects:

type BigObject = {
 dom: HTMLElement,
 count: number
}

This object is defined within a constructor of a class, but by a function called inside the constructor:

class Starter {

  bigObject: BigObject;

  constructor() {
    // A lot of code here, so I can't add more clutter
    this.initialize();
  }

  initialize() {
    this.bigObject.dom = document.getElementByID("app");
    this.bigObject.count = 0; 
  }
}

Initially, when I define the properties in the constructor, everything works fine. But when I define them in the initialize function (even though it's called in the constructor), TypeScript informs me that the object has no initializer...

Furthermore, this object will carry important data throughout my application and I'd like to use it in other places. I prefer not to define its properties as possibly undefined (with a question mark) because I perform many checks with exceptions and I am confident that its properties are defined when I use it. Additionally, since I'll be using it frequently, I want to avoid checking if bigObject.dom is defined every time I access it.


So, when I use question marks, the definition of the object is correct in the Starter class but I need to check it each time I use it. When I don't use question marks, I don't have to verify its properties but the definition fails.

Can anyone offer some guidance on this issue?

I attempted to provide a basic example of my situation, but in reality, it pertains to a game engine. In this context, the "BigObject" represents an object with services that are distributed across the app. And by "when I use it," I mean when the game engine is running and the services' definitions have been verified.

Answer №1

It is essential to initialize the property when creating your Starter instance. This step cannot be skipped. There are two primary methods to achieve this:

  • Initialize in the constructor:

    class Starter {
      bigObject: BigObject;
      constructor() {
        // …
        this.bigObject = {
          dom: document.getElementByID("app"),
          count: 0,
        };
      }
    }
    
  • Set as a class field:

    class Starter {
      bigObject: BigObject = {
        dom: document.getElementByID("app"),
        count: 0,
      };
      constructor() {
        // …
      }
    }
    

Now, you might think

There's already a lot of code [in the constructor], so I don't want to make it messier

This is where a helper function comes in handy. In your specific scenario, even though there aren't many individual properties of the Starter, they are all grouped together in a BigObject. This arrangement makes it easier to construct the entire object outside of the constructor. Instead of using an initialize method, which poses issues like calling it on an uninitialized instance or forgetting to call it, consider using a helper function that returns the big object. This helper function can be a standalone free function or a static class method. Simply invoke it from either the constructor or the class field initializer. You could also pass the bigObject as a parameter to your constructor for added flexibility.

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

How can I ensure that the size of the Dropdown Menu Item matches its parent in both Bootstrap and CSS styles?

I am working on a navigation bar that has a dropdown menu which appears on hover. I want the size of the dropdown menu items to match the size of the parent element. Here is an image for reference: https://i.stack.imgur.com/oNGmZ.png Currently, the "One ...

Guide to changing the checkbox value using JavaScript

Describing the Parent Element: <span style="background: yellow; padding: 50px;" onClick="setCheckBox()"> <span> </span> <input type="checkbox" name="f01" value="100"> </span> ...

When the collapsed navbar is displayed, elements are pushed beyond the boundaries of their parent container (Bootstrap 5)

Introduction Utilizing Bootstrap 5 (included with webpack 5), I am implementing the grid system and collapse function to design the homepage of this website, featuring 2 sidebars that collapse into a top bar. On mobile devices, the navigation collapses a ...

leveraging the tsconfig path for the source directory in the Next.js Image component

I'm attempting to store the path of my assets folder in the tsconfig file and then use it in the src attribute of the Image component, but for some reason it's unable to locate the address! This is what's in my tsconfig.js file: "paths ...

Utilizing array iteration to display images

I am having trouble getting the images to display on my card component. The description appears fine, but the images are not rendering properly even though I have the image data in an array. Here is the Card Component code: export const Card = (props) =&g ...

Navigating string primitives when using AngularJS and $http: Tips and Tricks

A function in ASP.NET Web Api is returning a simple string as JSON data. However, when calling this function from AngularJS, the returned value is surrounded by quotes instead of being a plain string: return $http.post('/api/orders', data).then ...

Retrieve the text content from the HTML document

I'm facing a beginner's challenge. I have a div element and I want to extract the URL from the data-element attribute into a .json file Is there a way to do this? <div content="" id="preview" data-element="http://thereislink" class="sample ...

The issue with displaying inline block is that the divs are not appearing side by side on the

Two of my div elements, namely form-panel and data-panel, are currently not aligned on the same line. How can I use display:inline-block to align them in a single line? Please review the code provided below. I have already used display:inline-block on both ...

Is there a way to provide a dynamic value for the p:remoteCommand ajax call?

My issue involves a p:dataTable that contains p:commandLink elements. I need to initiate an ajax call with parameters when the mouseover event occurs. After some research, it became clear that commandLink cannot trigger an ajax call on mouseover directly - ...

Vuetify Autocomplete that allows for adding values not in the predefined list

I am utilizing a vuetify autocomplete component to showcase a list of names for users to select from. In the case where a user enters a name not on the list, I want to ensure that value is still accepted. Check out my code snippet below: <v-autocomplete ...

What determines the priority of execution in the execution context stack?

Check out this insightful tutorial on execution context in JavaScript here. It's interesting how the order of invoking functionA() and console.log("GlobalContext") differs in terms of writing code versus the execution context stack. I'm curious, ...

Is there a way to convert a json array to a javascript array in AngularJs?

I am new to Angular and front-end development and facing a challenge that I can't seem to overcome. After reassigning one variable to another: $scope.testarray = $scope.todos; only the 'todos' data is being displayed when using Angular bind ...

Tips on customizing image borders/masks with hover effects

Is there a React library or a simple CSS trick to create an image's canvas cropping effect on hover? For example, similar to this: Thanks in advance! ...

Altering the input type of a cloned element in Internet Explorer results in the loss of the value

When I have checkbox inputs displayed in a modal with preset value attributes, upon clicking "OK", I clone them and change their input types to hidden, then append them to a div in the document body. However, when trying to retrieve their values using jQue ...

bespoke JavaScript confirmation dialogue box

After customizing a confirmation box for the logout feature, I encountered an issue. When the user presses cancel, the box closes and control remains on the same page as expected. However, when the user clicks yes to logout, nothing happens. Could anyone p ...

Whenever I navigate to this specific route, I consistently encounter an error message in my console

VM28353:1 Error: Unexpected token 'o' found in JSON at position 1 at JSON.parse (<anonymous>) at getUser (auth.js?c7d4:11) at wrappedGetter (vuex.esm-browser.js?5502:335) at Object.eval [as getUser] (vuex.esm-browser.js?5502 ...

React Hook is failing to trigger an update

Learning React and JavaScript has been quite a challenge for me, especially when it comes to understanding React Hooks and the issue of them not updating sometimes. I have tried searching online but either end up with solutions for class-based components o ...

Node.js implementation for processing batches of data from the Youtube Data API

I'm looking to leverage the Youtube API for batch processing multiple video ids in a single request. Currently, I'm able to successfully make individual requests by appending the video id, request parameters, and API key to the following url: ? ...

Revised: "Mastering the Art of using useLoaderData Properly with Remix V2

It seems that the correct way to type useLoaderData has changed since V2. export const loader = async () => { return json({ messages: [...] }) } // In component... const { messages } = useLoaderData<typeof loader> Prior examples show it type ...

What steps should I follow to ensure that TypeScript is aware of the specific proptypes I am implementing?

Is there a way to instruct TypeScript on the prop types that a component is receiving? For example, if multiple is set to true, I would like TypeScript to expect that selectValue will be an array of strings. If it's not present, then TypeScript should ...