The convention for TypeScript getter and setter methods

What is the recommended practice in TypeScript for defining class attributes?

In the Angular 2 demo (The Heroes Tour from angular.io), all attributes are declared as public:

export class Hero {
   id: number;
   name: string;
}

This allows for instantiation in two different ways:

var hero: Hero = new Hero();
hero.id = 0;
hero.name = "hero";

or

var hero2: Hero = {id : 0, name: "hero"};

Is there a preferred convention similar to Java's style, like this example below?

export class Hero {
   private id: number;
   private name: string;

   setId(id: number): Hero {
      this.id = id;
      return this;
   }

   setName(name: string): Hero {
      this.name = name;
      return this;
   }

   getId(): number {
      return this.id;
   }

   getName(): string {
      return this.name;
   }
}

Usage (example):

var hero: Hero = new Hero();
hero.setId(0).setName('hero');

var hero2: Hero = new Hero().setId(0).setName('hero');

Answer №1

When it comes to programming languages, Java is known for being statically compiled. If you were to create a JAR library in Java and expose a class like this:

class Foo {
  public int bar;
}

and then decide to update your logic later on like so:

class Foo {
  private int _bar;
  public int getBar() { return _bar - 1; }
  public void setBar(int v) { _bar = v + 1; }
}

Any code that relies on your JAR file will break and require updates and recompilation. This is why it's strongly advised against exposing raw public fields in Java.

In contrast, TypeScript, which is a superset of JavaScript, operates within a dynamic language environment. All linking is done dynamically, allowing you to release a library with a class defined simply as:

class Foo {
  bar: number
}

If you make changes down the line such as:

class Foo {
  private _bar: number
  get bar() { return this._bar - 1 }
  set bar(v: number) { this._bar = v + 1 }
}

Users of your TypeScript library will smoothly transition to the updated version without any noticeable impact.

Answer №2

When working with TypeScript, your code will eventually be transformed into clean JavaScript code. In situations where you require actions to be taken before or after setting a value, such as logging, you will need to implement this functionality yourself.

If these additional functionalities are not required, using getters and setters may be unnecessary and considered over-engineering. The process of instantiating objects and setting values in TypeScript is similar to that in Java.

For example:

export class Person{
    public name: string;
    public anotherAttribute: string;
    private age: number;
    private _birth: Date;

    public set birth(birth: Date){
       this._birth = birth;
       this.age = calculateAge(birth);
    }
    .......
}


let person: Person = new Person();
person.name = "John";
......

Answer №3

Does Java have a standard style convention similar to this one?

Yes, you can follow a similar convention in Java (which I have done before). In Java, people also commonly use getter / setter methods like this:

public class Hero {
   private int id;

   public void setId(int id) {
      this.id = id;
   }
}

It's important not to overload setters with complex logic: https://basarat.gitbooks.io/typescript/content/docs/tips/propertySetters.html. Personally, I prefer explicit function calls.

Hero hero2 = new Hero();
hero2.setId(0);

This reflects the structural aspect of TypeScript's type checking, which can be seen as both a weakness and a convenience. Learn more about it here: More on this.

Answer №4

Is there a specific Java style convention?

It is possible to use Java style conventions if you prefer, but since TypeScript and Java are different languages, it would be more practical to follow TypeScript conventions. In TypeScript, it is common practice to directly access "members" using the dot notation, which makes the code more readable for those familiar with TypeScript. This approach may also appeal to Java developers. While I have a fondness for Java, adhering to coding conventions in this case would involve unnecessary repetition.

Many developers joke about languages like Java being excessively verbose.

In summary, it is recommended to use myObject.myMember for direct member access.

Answer №5

Do you prefer the Java style because of the additional code involved in setting each property individually? If that's the case, you can simply declare the properties within the constructor of the class.

Superhero Class

export class Superhero {
  constructor(public id?: number, public name?: string) {}
}

Property Declarations

const hero1 = new Superhero(1, 'Batman');
const hero2 = new Superhero();

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

Turning Typescript into Javascript - the How-To Guide

Currently following Shopify's Node Api tutorial to implement a Redis store in my project. The tutorial provides code in typescript, but my entire project is in javascript (React/nextjs). I've been struggling to convert the code to javascript for ...

Tips for determining if an array of objects, into which I am adding objects, contains a particular key value present in a different array of objects

I've been working on this and here is what I have tried so far: groceryList = []; ngOnInit() { this._recipesSub = this.recipesService.recipes.subscribe((receivedData) => { this.loadedRecipes = receivedData.recipes; }); } onCheckRecipe(e) { ...

Ensure that an input field is mandatory only when another field contains a value in Angular 6

I am working with two input controls in my Angular 6 project. The first control looks like this: <input type="text" [(ngModel)]="UserData.FirstControl" formControlName="FirstControl" class="form-control" maxlength="8" > T ...

Implementing tailwindcss styles in a typescript interface with reactjs

In my code, I have a file named types.ts that defines an interface called CustomCardProps. I pass this interface to the CustomCard component within the home.tsx file. Additionally, I have a folder named constant with an index.ts file where I store values o ...

Using Typescript Type Guard will not modify the variable type if it is set in an indirect manner

TL;DR Differentiation between link1 (Operational) vs link2 (not functional) TypeGuard function validateAllProperties<T>(obj: any, props: (keyof T)[]): obj is T { return props.every((prop) => obj.hasOwnProperty(prop)) } Consider a variable ms ...

Prevent ESLint from linting files with non-standard extensions

My .estintrc.yaml: parser: "@typescript-eslint/parser" parserOptions: sourceType: module project: tsconfig.json tsconfigRootDir: ./ env: es6: true browser: true node: true mocha: true plugins: - "@typescript-eslint" D ...

implement dynamic interaction between two dropdown menus in angular 4

uniqueComponent.html <select data-placeholder="All Categories" class="category" value="category.category.categoryName"> <option selected="selected" style="display:none">Select Category</option> <option class="select" *ngFor="let c ...

Dealing with an If-else situation in an Effect to decide between throwing an error or retrieving a response from an API

I'm currently working on implementing a condition that will determine whether to throw an error or proceed with calling an API to retrieve a response. I'm seeking guidance on the best approach for this task. My knowledge of rxjs is limited as I ...

What is the best way to link three different types of http requests in succession and adaptively?

Is it possible to chain together 3 types of http requests correctly, where each request depends on data from the previous one and the number of required requests can vary? In my database, there is a team table with a corresponding businessId, a supervisor ...

Error encountered in Angular build optimization process: TypeError - the function this._createContainer is not recognized

When compiling an Angular 7.2.5 application with --prod, a strange run-time error occurs. The stack trace shows: ERROR TypeError: this._createContainer is not a function at bg.pa (Viewer.js.pre-build-optimizer.js:143) at new bg (Modeler.js.pre-bu ...

Troubleshooting problems with the Quora pixel after refreshing the page

Having a strange issue with the Quora pixel integration on Angular. I have added the script in the HTML code as follows: ! function(q, e, v, n, t, s) { if (q.qp) return; n = q.qp = function() { n.qp ? n.qp.apply(n, arguments) : n.queue.push ...

Troubleshooting Problem with ES6 String Literals/Typescript in Chrome Developer Tools

I'm currently immersed in a project that involves Typescript and some of the ES6 features it offers, such as ES6 String Literals like `Something ${variable} Something else`. During my debugging process, I decided to set a breakpoint in my typescript ...

When attempting to assign a 'string' type to the @Input property, I am receiving an error stating that it is not assignable to the 'PostCard Layout' type

Encountering an issue The error message 'Type 'string' is not assignable to type 'PostCard Layout'' is being displayed A parent component named page-blog.component.html is responsible for defining the class styles and passi ...

Guide to forming an array by extracting specific properties from a nested JSON array using javascript

Currently, I have this list: list = { id: 1, arr: [ {index : 1 , description: "lol" , author: "Arthur"}, {index : 2 , description: "sdadsa" , author: "Bob"}, {index : 3 , desc ...

Issue with Angular overlay not appearing correctly when using a bootstrap sidebar template

My attempt to incorporate an overlay into a component by clicking a button mirrored this example: https://stackblitz.com/edit/overlay-demo-fv3bwm?file=app/app.component.ts However, upon integrating it into my component, the overlay elements (in this ...

What is the best way to imitate an imported class definition using sinon?

Having trouble mocking an import in my spec file and seeking help to identify the issue. This is the exported class for the Database connection: import Knex from 'knex'; import { merge } from 'lodash'; import knexfile from '../kn ...

Issue: Error thrown due to attempting to access the 'push' property of an undefined element in an Angular child component

I have an array in my child component's element @Input() listAnswer: any; changestyle(event) { let activeSpan = event.target; this.listAnswer.push(activeSpan.innerText.trim()); } I am passing this variable from the parent component < ...

Vuetify's v-data-table is experiencing issues with displaying :headers and :items

I'm facing an issue while working on a Vue project with typescript. The v-data-table component in my Schedule.vue file is not rendering as expected. Instead, all I can see is the image below: https://i.sstatic.net/AvjwA.png Despite searching extensi ...

Utilizing AngularJS and TypeScript for seamless two-way data binding: a guide for synchronizing controller and directive interaction

Seeking to delegate my table with filtering and sorting functions as a directive. To incorporate two-way data binding, I have implemented the following: public bindToController = { cars: "=" }; This setup is necessary because when a car in the tabl ...

Modifying the dimensions of mat-card in Angular Material

https://i.stack.imgur.com/CP16N.png I am struggling to make both components the same height, similar to the left form. I have tried adjusting margins and padding but nothing seems to work. Below is the HTML code for the parent element: <mat-tab label= ...