Discovering the optimal method for modifying the state of an object within Object-Oriented Programming using Typescript

I have implemented Object Oriented Programming in my project and I am exploring ways to effectively change the state of an object while ensuring its integrity. Although I have created a code snippet for this purpose, I am curious if there are more optimized methods or established design patterns that can be used in OOP development.

Below is the excerpt of the code I have developed:

export class AccessProfile {

    id!: number;
    active!: boolean;
    name!: string;
    createdAt!: Date;
    createdBy!: string | null;
    createdFrom!: SystemModule;
    updatedAt!: Date;
    updatedBy!: string | null;
    updatedFrom!: SystemModule;
    environment!: Environment;
    hierarchy!: number | null;
    permissions!: Set<string>;


    public update(
        {
            updatedFrom,
            updatedBy = null,
            name,
            active,
            hierarchy,
            permissions
        }: {
            updatedFrom: SystemModule,
            updatedBy?: string | null,
            name?: string,
            active?: boolean,
            hierarchy?: number | null,
            permissions?: Set<string>,
        }
    ) {

        const backup = {
            name: this.name,
            active: this.active,
            hierarchy: this.hierarchy,
            permissions: this.permissions
        };

        try {

            if (name !== undefined) {
                name = AccessProfile.sanitizeName(name);

                if (this.name !== name) {
                    AccessProfile.validateName(name);
                    this.name = name;
                }
            }

            if (active !== undefined && this.active !== active) {
                this.active = active;
            }

            if (hierarchy !== undefined) {
                hierarchy = AccessProfile.sanitizeHierarchy(hierarchy);

                if (this.hierarchy !== hierarchy) {
                    AccessProfile.validateHierarchy(hierarchy);
                    this.hierarchy = hierarchy;
                }
            }

            if (
                permissions !== undefined
                && !permissionsAreEqual(permissions, this.permissions)
            ) {
                this.permissions = permissions;
            }

            if (this.hierarchy !== backup.hierarchy && this.permissions !== backup.permissions) {
                AccessProfile.validateHierarchyAndPermissions({
                    hierarchy: this.hierarchy,
                    permissions: this.permissions
                });
            } else if (this.hierarchy !== backup.hierarchy) {
                AccessProfile.validateHierarchyAndPermissions({
                    hierarchy: this.hierarchy,
                    permissions: backup.permissions
                });
            } else if (this.permissions !== backup.permissions) {
                AccessProfile.validateHierarchyAndPermissions({
                    hierarchy: backup.hierarchy,
                    permissions: this.permissions
                });
            }

            this.updatedFrom = updatedFrom;
            this.updatedBy = updatedBy;

            this.updatedAt = new Date();
            return this;
        } catch (err) {

            this.name = backup.name;
            this.active = backup.active;
            this.hierarchy = backup.hierarchy;
            this.permissions = backup.permissions;

            throw err;
        }
    }


}

Answer №1

I'm currently exploring the most effective method to change the state of an object while ensuring its consistency.

In my opinion, the best and cleanest approach is to structure your update method in two phases: 1) validate and adjust arguments (and throw an error on invalid data); 2) assign the valid data to instance properties. Below is a simple example, with additional suggestions included in the code.

It's worth noting that working with single arguments/variables versus objects and their properties is nearly identical, and the main focus should be on readability. While using Object.assign can reduce the lines of code, it may not allow for optimization by only assigning changed properties.

insert unique interface, class and method examples here...

Link to playground

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

Is it possible to change the value of a react-final-form Field component using the onSelect function?

I am currently working on a React application using TypeScript and incorporating the Google Places and Geocoder APIs through various React libraries such as "react-places-autocomplete": "^7.2.1" and "react-final-form": "^6.3.0". The issue I'm facing ...

Angular 4: Implementing toggle switch functionality in Angular 4 by binding boolean values retrieved from the database

Within my application, I am facing an issue with binding a toggle switch to data stored in the database. The data in the database is represented by a field called Status, which can have values of True or False. My goal is to incorporate toggle switch butto ...

Simple method for wrestling with objects in TypeScript HTTP POST responses

Can anyone help me understand how to extract information from an object received through an HTTP POST request? Below is the code I am using: this.http.post(url, user, httpOptions).subscribe(result => { console.log(result.status); }); The issue aris ...

Vue Deep Watcher fails to activate when the data is altered

While the countdown timer is functioning properly, it seems that the deep watcher is not working as expected. Despite attempting to log the new value of seconds in the console, it does not display anything even though the countdown timer continues to funct ...

Ensuring Proper Tabulator Width Adjustment Across All Browser Zoom Levels

<div id="wormGearTabulatorTable" style="max-height: 100%; max-width: 100%; position: relative;" class="tabulator" role="grid" tabulator-layout="fitDataTable"><div class="tabulator-header" role="rowgroup"><div class="tabulator-header-co ...

Using React with Typescript: How to pass a function as a prop to a child component and call it from within

I am trying to pass a function as a prop to a child component so that the child can call it. Here is my parent component: interface DateValue { dateValue: string; } const Page: React.FC = () => { const dateChanged = (value: DateValue) => { ...

What is the proper way to access the current value of a computed property from within its own computation method?

Our goal is to activate a query when a string reaches a length of 3 characters or more, and keep it activated once triggered. Leveraging the Vue 2 Composition API, we have implemented a reactive object to manage the status of queries: import { computed, de ...

Error Encountered | Invalid Operation: Unable to access attributes of undefined (referencing 'CodeMirror')

Error image on chrome Using Next.js 13 Encountering an error on Google Chrome, seeking a solution to fix it or possibly just ignore it. Not utilizing Codemirror and prefer not to use it either. Tried troubleshooting methods: Deleting ".next","node_ ...

Unexpected token { in Fuse-Box when using Typescript

Here's the beginning of my fuse.ts file import { CSSPluginOptions } from 'fuse-box/plugins/stylesheet/CSSplugin'; import { argv } from 'yargs'; import * as path from 'path'; import { CSSPlugin, CSSResourcePlugin, Env ...

Incorporating jsbi into a TypeScript project while adhering to strict mode

I have been developing a TypeScript library that relies on native BigInts. While it functions perfectly in Chrome, I encountered some issues with Safari. After some research, I stumbled upon the jsbi "polyfill" that seems to solve this problem. Unfortunat ...

Am I effectively implementing async await in TypeScript?

I'm not quite sure if I'm using the async/await functionality correctly in my TypeScript and Protractor code. Looking at the code snippet below, the spec uses await to call the page object, which itself is an async/await function. The page object ...

Encountered an issue while constructing swagger in Laravel project using Vite

After running npm run build in Laravel, I encountered the following error. Interestingly, everything works fine when I run npm run dev. However, the error below occurs during the build process: rendering chunks (2)...warnings when minifying css: ▲ [WARNI ...

While attempting to utilize inner class functions in Node JS, an error is being encountered

I've been delving into Node JS and exploring how to implement an OOP structure within node. I've created a simple class where I'm using functions to verify and create users in a database. However, I'm encountering a TypeError when attem ...

Troubleshooting tsconfig configuration issue in Visual Studio Code for ExpressJS with TypeScript and Vitest integration testing

Let's dive right in with an illustration: Here is a simplified version of my project structure: src/ app.ts test/ integration/ example.spec.ts tsconfig.json tsconfig.json The main tsconfig.json file includes these settings: { & ...

Removing HTML Tags in Ionic - A How-To Guide

After utilizing Ionic 3 to retrieve data from a WordPress API, I am encountering an issue with displaying the content on the app UI. The problem arises from the presence of HTML tags within the content being printed along with the text. While seeking solut ...

Is there a way for me to retrieve the bodyHeight attribute of ag-grid using public variables or data?

Working on a project using ag-grid community react. The main feature is a scrollable section filled with data, which can range from one piece to millions of pieces. I'm also incorporating a footer component for the grid that needs to adjust its height ...

Transferring data between components in React by passing parameters through Links

When calling another component like <A x={y}/>, we can then access props.x inside component A. However, in the case of calling EditCertificate, the id needs to be passed to the component. I am using a Link here and struggling to pass the id successf ...

The specified 'IArguments' type does not qualify as an array type

Currently working on crafting a personalized logger. It's a fairly straightforward process, but I'm running into some errors that are muddying up my output. Here's what I have so far: @Injectable() export class Logger { log(...args: any ...

Setting multiple values on a form can be accomplished by using the appropriate form fields

When it comes to setting values on fields, I am aware that I can choose between using setValue or patchValue However, I am currently encountering a situation where I need to avoid setting the value on each field individually. Take a look at my f ...

Retrieve a mapping of keys from a generic object structure in TypeScript

I am trying to extract the key map from an object, and although I have created a function for this purpose, TypeScript is not happy with it. How can I resolve this issue without using acc: any? const origin = { a: 1, b: 'string', c: () =&g ...