Is it feasible for TypeScript class optional properties to default to a set value when not provided?

Is there a way to automatically set default values for class member properties if the user does not provide them?

I have created a customized class that includes an optional instance of another class:

export class MyClass1 {
    constructor() {
        this.name = "";
        this.classInstance = new MyClass2();
    }
    name: string;           // object's name
    classInstance?: MyClass2;
}

class MyClass2 {
    constructor() {
        this.name = "MyClass2 initial name";
    }

    name: string;
}

The data for MyClass1 is sourced from JSON, which means that sometimes the classInstance property can be undefined. In such cases, I want the MyClass1 constructor to assign new MyClass2() to the classInstance property by default.

This is how I create an instance of MyClass1:

let myNewClass: MyClass1 = {
    name: "MyClass"
}

Despite omitting the classInstance, I assumed that it would still take on the default value specified in the constructor. However, this was not the case. I even attempted removing the optional sign from the classInstance property, but encountered a compilation error because then the object had to match the structure of MyClass1. Although I tried casting to avoid errors, the issue persisted (and I'm unsure if the casting was done correctly):

let myNewClass: MyClass1 = {
    name: "MyClass"
} as MyClass1

In both scenarios, the classInstance did not receive the default value set in the constructor; it remained null/undefined.

For me, solving the casting dilemma or modifying the properties to be optional is acceptable as long as I can control the default values.

Answer №1

There seems to be an issue in this code snippet.

let myNewClass: MyClass1 = {
    name: "MyClass"
} as MyClass1

In this case, the object created is not actually an instance of MyClass1. It appears that the TypeScript type system was tricked into treating a plain object as a MyClass1 instance.

This will result in transpiling to

var myNewClass = { name: "MyClass" }
, without instantiating the MyClass1 class. That's the end of the story.

To achieve the desired outcome, it is recommended to pass values from JSON to the class constructor. Since object properties (classInstance) can be undefined, class properties should not rely on default values like

constructor({ classInstance = new MyClass2 }) { ... }
and need to be manually assigned:

export class MyClass1 {
    constructor(jsonMyClass1: MyClass1 = {}) {
        const { name, classInstance } = jsonMyClass1;
        this.name = 'name' in jsonMyClass1 ? name : "";
        this.classInstance = 'classInstance' in jsonMyClass1 ? classInstance : new MyClass2;
    }
    name: string;
    classInstance?: MyClass2;
}

let myNewClass: MyClass1 = new MyClass1({
    name: "MyClass"
});

If data is handled based on how it will be used by classes (e.g. using null for undefined values), the approach can be optimized to leverage the language features:

export class MyClass1 {
  constructor(jsonMyClass1: MyClass1 = {} as MyClass1) {
        const { name = "", classInstance = new MyClass2 } = jsonMyClass1;
        this.name = name;
        this.classInstance = classInstance;
    }
    name: string;
    classInstance: MyClass2;
}

let myNewClass: MyClass1 = new MyClass1({
    name: "MyClass",
    classInstance: null
});

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

Unsynchronized state of affairs in the context of Angular navigation

Within my Angular project, I am currently relying on an asynchronous function called foo(): Promise<boolean>. Depending on the result of this function, I need to decide whether to display component Foo or Bar. Considering my specific need, what woul ...

What is causing Angular 6 to fail in sending HTTP Get/Post requests?

In Angular 6, I have created a LoginService like this: @Injectable() export class LoginService { constructor(private http: HttpClient) { } login(): Observable<boolean> { var url = `${environment.baseAPIUrl}${environment.loginUrl}`; ...

When no values are passed to props in Vue.js, set them to empty

So I have a discount interface set up like this: export interface Discount { id: number name: string type: string } In my Vue.js app, I am using it on my prop in the following way: export default class DiscountsEdit extends Vue { @Prop({ d ...

"Encountered a problem while attempting to download the .xlsx file through http.get in an angular application interfacing

Attempting to download a .xlsx file using Angular 7 and web API in C#, encountering the following error: https://i.sstatic.net/7pwDl.png The code snippet from my service.ts is provided below: public exportExcelFile(matchedRows: string, reportInfoId: num ...

Performing unit testing on a Vue component that relies on external dependencies

Currently, I am in the process of testing my SiWizard component, which relies on external dependencies from the syncfusion library. The component imports various modules from this library. SiWizard.vue Imports import SiFooter from "@/components/subCompon ...

React-admin: Reference Input is only showing IDs instead of displaying my fields

I am currently working with a Reference input in react admin, but I am facing an issue where it displays the ids of the resource instead of the field I specified (status) and I am unsure why this is happening. Here is a snippet of my code: const Candidatur ...

Customize the text for the material icon

Can I customize an icon by using the following code: import FiberNewIcon from "@mui/icons-material/FiberNew"; Is there a way to add custom text to the icon? ...

Learn the process of adjusting the Time Zone in Angular2-HighCharts!

I've been struggling for a few days now trying to adjust the UTC time in an area chart using Angular2-HighCharts. The backend API is returning timestamps which I then inject into the chart, but each time it's being converted to "human time" with ...

What is the method for extracting the types of parameters from a function type while excluding a single parameter?

Suppose I have the following interface that defines a function: export declare interface NavigationGuard { (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext): NavigationGuardReturn | Promise<NavigationGuardReturn ...

Converting milliseconds into a date format

I am looking to change milliseconds into a string that displays the time duration. function convertMsToTime(ms) { return ('' + Math.floor(ms / 86400000) + 'd -' + Math.floor((ms % 10) / 60).toString().padStart(2, '0')); } ...

Encountering an error message that reads "State.Push is not a valid function" upon integrating

Currently, I am working on developing a Todo app using react-typescript and redux. During testing, I noticed that the app functions properly without redux-persist, displaying the list of added tasks. However, upon integrating redux-persist, the store does ...

Limiting the data types of array elements applies to variables, not to indexes

type Soccer = { ball: string } type Basketball = { jump: string } type Data = Soccer[] | Basketball[] if ('ball' in data[index]) { // type guard not effective here. <MyComponent something={data[index]} /> // data: Soccer[] | Basketball[] ...

Angular 6 - Issue with ngModel displaying [object Object] instead of data in binding

Within my code, there is a variable named "data" that holds the following information: { id: 1, date: "2018-03-13T16:18:03", date_gmt: "2018-03-13T16:18:03", guid: {}, modified: "2018-05-03T17:25:36", modified_gmt: "2018-05-03T17:25:36", slug: "hello-worl ...

Error message "Property shorthand expected in object literal" occurs when assigning a value to a variable as an object

Here is an example of an object that I have: { element: 'tool-app', file: '/tool-app.js', icon: 'csr-icon', name: 'Planning view', id: 'planning-view' } To simplify thi ...

How can I simulate or manipulate the element's scrollHeight and clientHeight in testing scenarios?

In my JavaScript code, I have a function that checks if an HTML paragraph element, 'el', is a certain size by comparing its scrollHeight and clientHeight properties: function isOverflow(element: string): boolean { const el = document.getEleme ...

The filter pipe in Angular 7 is not functioning properly

Upon page loading and API call initiation, I am encountering an issue with the ngFor loop not displaying all the values. However, when I manually input a search query in the search box for filtering, the functionality works flawlessly. My goal is for all v ...

Utilizing TypeScript with Msal-React for Prop Type Validation

I'm currently implementing authentication in my app using msal-React. Within my app, I have a component that utilizes msalcontext and is wrapped by withMsal: function App(props: any) { return ( <> <AuthenticatedTemplate> ...

Eliminate nested object properties using an attribute in JavaScript

I am working with a nested object structured like this const data = [ { id: '1', description: 'desc 1', data : [ { id: '5', description: 'desc', number :1 }, { id: '4', description: 'descip& ...

Issue with Angular: Global variable not updating within Subscription function

I'm encountering difficulties with updating a global variable in Angular 7 by using TypeScript. I am utilizing a service that retrieves JSON data from a database via a Restful API The service : export class myService { constructor(private client ...

"Error Popping Up: Duplicate Identifier Detected in Popper.js

I've hit a roadblock trying to resolve this error or identify its root cause. Despite no changes in the code, I suspect it may be due to an updated NPM package. The error log displayed in the console is specific to an Angular2 application. ERROR in [ ...