A programming element that is capable of accessing a data member, but mandates the use of a setter method for modifications

I am unsure whether I need a class or an interface, but my goal is to create an object with a member variable that can be easily accessed like a regular variable. For example:

interface LineRange {
    begin: number;
    end: number;
}

However, I want the value to only be set using a separate setter() function to prevent accidental modifications.

For instance:

// Simply initialize the required class, interface, or any other necessary component
let item: LineRange;

// Access it as follows:
const foo: number = item.begin;

// Prevent modification:
const bar: number = item.begin++;

// Allow setting, but only with the specific setter method:
item.setBegin(42);

Is this achievable? If so, how?

Note: I prefer not to introduce a getBegin() function solely for reading a basic member

Answer №1

To transform the begin into an accessor property with only a getter, you can create a method called setBegin:

class LineRange {
    constructor(
        private _begin: number,
        private _end: number
    ) {
    }
    get begin(): number {
        return this._begin;
    }
    setBegin(begin: number): void {
        this._begin = begin;
    }
    get end(): number {
        return this._end;
    }
    setEnd(end: number): void {
        this._end = end;
    }
}

Here is how you can use it:

const lr = new LineRange(0, 0);
console.log(lr.begin); // 0
// lr.begin = 42; <== Would be an error
lr.setBegin(42); // Works
console.log(lr.begin); // 42

You can also define it as an interface (which the implementation above would support if you change the name):

interface LineRange {
    readonly begin: number;
    setBegin(begin: number): void;
    readonly end: number;
    setEnd(end: number): void;
}

Check out the live example on the playground


Note:

I prefer not to introduce a getBegin() function just for reading a simple member.

It's important to mention that using an accessor property does technically introduce a function. However, it doesn't require using function call syntax when accessing the property; the function call is implicit.

If you want to avoid this, you can hide the class and only use the interface type:

interface LineRange {
    readonly begin: number;
    setBegin(begin: number): void;
    readonly end: number;
    setEnd(end: number): void;
}

class LineRangeClass implements LineRange {
    constructor(
        public begin: number,
        public end: number
    ) {
    }
    setBegin(begin: number): void {
        this.begin = begin;
    }
    setEnd(end: number): void {
        this.end = end;
    }
}

In usage, ensure to declare lrc explicitly as LineRange instead of LineRangeClass:

const lrc: LineRange = new LineRangeClass(0, 0);
console.log(lrc.begin);
// lrc.begin = 42; <== Would be an error
lrc.setBegin(42); // Works
console.log(lrc.begin);

Keep in mind that without specifying a type for lrc, it will default to LineRangeClass, allowing setting the begin property:

const lrc = new LineRangeClass(0, 0);
console.log(lrc.begin);
lrc.begin = 42; // <== NOT an error, because `lrc` is `LineRangeClass`
lrc.setBegin(42); // Works
console.log(lrc.begin);

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

What is the best way to retrieve class members using component properties?

I am looking to implement a mixin for setting the header and meta data in my project. I recently discovered vue-meta, which seems to work really well for this purpose. However, I am still getting acquainted with TypeScript and class-based components. How ...

What is the most efficient way to remove all typed characters from fields when clicking on a different radio button? The majority of my fields share the same ngModel on a separate page

Is there a way to automatically clear all typed characters in form fields when switching between radio buttons with the same ngModel on different pages? I noticed that the characters I type in one field are retained when I switch to another radio button. ...

Sharing information between different pages in NEXT.js version 14

After performing a fetch and receiving a successful response containing data as an object, I use router.push to redirect the page to another one where I want to display the fetched data. const handleSubmit = async (event: any) => { event.preventDefa ...

Learn how to implement icons within Textfield components using Material-UI and TypeScript in React

I have successfully created a form with validation using TypeScript Material UI and Formik. Now, I am looking to enhance the visual appeal by adding a material UI Icon within the textfield area. Below is a snippet of my code: import React from 'reac ...

Is the TypeScript compiler neglecting the tsconfig.json file?

I am new to TypeScript and currently exploring how to set it up in WebStorm. One of the first steps I took was creating a tsconfig.json file in the main directory of my project and updating the built-in TypeScript compiler to version 1.6.2. However, despit ...

The error at core.js:4002 is a NullInjectorError with a StaticInjectorError in AppModule when trying to inject FilterService into Table

While exploring PrimeNg Table control in my application - as a beginner in PrimeNg & Angular, I encountered an error No provider for FilterService! shown below: core.js:4002 ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppMo ...

Having trouble looping through an array in Angular 2?

I am currently using a FirebaseObjectObservable to retrieve the value of a property from my firebase database. The property can have multiple values, so I stored them in a local array variable. However, I ran into an issue while trying to iterate through ...

The React Quill interface is unable to load due to an undefined window

I recently integrated React Quill into my Next.js project and everything was functioning properly. However, I encountered an issue when attempting to incorporate ImageResize into the editor. Upon adding the line Quill.register('modules/imageResize&ap ...

Ways to set a default value for a function that returns an unknown type in TypeScript

In my code, I have a customizedHook that returns a value of type typeXYZ || unknown. However, when I try to destructure the returned value, I encounter an error TS2339: Property 'xyz' does not exist on type 'unknown', even though the da ...

What is the best way to instantiate objects, arrays, and object-arrays in an Angular service class?

How can I nest an object within another object and then include it in an array of objects inside an Angular service class? I need to enable two-way binding in my form, so I must pass a variable from the service class to the HTML template. trainer.service. ...

Issue with Angular Swiper carousel: Error message pointing to node_modules/swiper/angular/angular/src/swiper-events.d.ts

I am attempting to implement a carousel in Angular using Swiper (). An error message is appearing: Error: node_modules/swiper/angular/angular/src/swiper-events.d.ts:3:50 - error TS2344: Type 'SwiperEvents[Property]' does not meet the constraint ...

I am eager to perform DOM manipulation similar to jQuery but within the context of Angular 6

Is there a way to modify the background color of the main div when a button is clicked? <div> <p>I'd like to be able to change the background color of the parent div by clicking a certain button. </p> <button (click)=" ...

Sending data between components in Angular can be achieved by using various methods. One common approach is to utilize

I am encountering an issue with a component named customers.component Below is the code from the customers.component.ts file: @Component({ selector: 'app-customer', templateUrl: './customer.component.html', styleUrls: ['./cu ...

Establishing the placement of map markers in Angular

Currently, I am in the process of developing a simple web application. The main functionality involves retrieving latitude and longitude data from my MongoDB database and displaying markers on a map, which is functioning correctly. However, the issue I&apo ...

Authenticate the digital signature created with the ED25519 algorithm

My current task involves verifying a digital signature that was signed using ED25519 with typescript Crypto, but I need to verify it in Java using BouncyCastle. The code snippet I am using for verification is as follows: byte[] decodedSign = Base64.getDeco ...

The variable <variable> is not meeting the 'never' constraint. Error code: ts(2344)

Currently, I am attempting to utilize Supabase alongside TypeScript. However, I encounter an error when trying to use functions like insert(), update(), upsert(), etc. Specifically, the issue arises when declaring the object I want to declare: "Type & ...

The collapsible tree nodes overlap one another in the D3.js visualization

I'm currently working on integrating a d3 code into Power BI for creating a collapsible tree structure. Each node in the tree is represented by a rectangular box, but I've run into an issue where nodes overlap when their size is large. Below is t ...

Looking for a solution to the TypeScript & Mantine issue of DateValue not being assignable?

The required project dependencies for this task are outlined below: "dependencies": { "@mantine/core": "^7.6.2", "@mantine/dates": "^7.6.2", "@mantine/form": "^7.6.2", &q ...

The compiler is showing an error with code TS5023, indicating that the option 'strictTemplates' is not recognized

When trying to compile my Angular application (v10), I encountered the following error message. An unexpected issue has occurred: tsconfig.json:14:5 - error TS5023: Unknown compiler option 'strictTemplates'. 14 "strictTemplates": t ...

What is the best way to implement a dynamic mask using imask in a React

I have a question regarding the implementation of two masks based on the number of digits. While visually they work correctly, when I submit the form, the first mask is always selected. How can I resolve this issue? My solution involves using imask-react ...