[typescript] get and set in TypeScript

I'm trying to create get and set method for a property:

private _name: string;

Name() {
    get:
    {
        return this._name;
    }
    set:
    {
        this._name = ???;
    }
}

What's the keyword to set a value?

This question is related to typescript

The answer is


You can write this

class Human {
    private firstName : string;
    private lastName : string;

    constructor (
        public FirstName?:string, 
        public LastName?:string) {

    }

    get FirstName() : string {
        console.log("Get FirstName : ", this.firstName);
        return this.firstName;
    }
    set FirstName(value : string) {
        console.log("Set FirstName : ", value);
        this.firstName = value;
    } 

    get LastName() : string {
        console.log("Get LastName : ", this.lastName);
        return this.lastName;
    }
    set LastName(value : string) {
        console.log("Set LastName : ", value);
        this.lastName = value;
    } 

}

Based on example you show, you want to pass a data object and get a property of that object by get(). for this you need to use generic type, since data object is generic, can be any object.

export class Attributes<T> {
    constructor(private data: T) {}
    get = <K extends keyof T>(key: K): T[K] => {
      return this.data[key];
    };
    set = (update: T): void => {
      //   this is like spread operator. it will take this.data obj and will overwrite with the update obj
      // ins tsconfig.json change target to Es6 to be able to use Object.assign()
      Object.assign(this.data, update);
    };
    getAll(): T {
      return this.data;
    }
  }

< T > refers to generic type. let's initialize an instance

 const myAttributes=new Attributes({name:"something",age:32})

 myAttributes.get("name")="something"

Notice this syntax

<K extends keyof T>

in order to be able to use this we should be aware of 2 things:

1- in typestring strings can be a type.

2- all object properties in javascript essentially are strings.

when we use get(), type of argument that it is receiving is a property of object that passed to constructor and since object properties are strings and strings are allowed to be a type in typescript, we could use this <K extends keyof T>


I think I probably get why is it so confusing. In your example, we wanted getters and setters for _name. But we achieve that by creating getters and setters for an unrelated class variable Name.

Consider this:

class Car{
    private tiresCount = 4;
    get yourCarTiresCount(){
        return this.tiresCount ;
    }
    set yourCarTiresCount(count) {
        alert('You shouldn't change car tire count')
    }
}

Above code does following:

  1. get and set create getter and setter for yourCarTiresCount (not for tiresCount).

The getter is :

function() {
    return this.tiresCount ;
}

and the setter is :

function(count) {
    alert('You shouldn't change car tire count');
}

Meaning, every time we do new Car().yourCarTiresCount, getter runs. And for every new Car().yourCarTiresCount('7') setter runs.

  1. Indirectly create getter, but not the setter, for private tireCount.

If you are looking for way to use get and set on any object (not a class) Proxy may be usefull: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

const target = {
  message1: "hello",
  message2: "everyone"
};

const handler3 = {
  get: function (target, prop, receiver) {
    if (prop === "message2") {
      return "world";
    }
    return Reflect.get(...arguments);
  },
};

const proxy3 = new Proxy(target, handler3);

console.log(proxy3.message1); // hello
console.log(proxy3.message2); // world

Note: be aware that this is new api not supported and required polifill for older browsers


Ezward has already provided a good answer, but I noticed that one of the comments asks how it is used. For people like me who stumble across this question, I thought it would be useful to have a link to the official documentation on getters and setters on the Typescript website as that explains it well, will hopefully always stay up-to-date as changes are made, and shows example usage:

http://www.typescriptlang.org/docs/handbook/classes.html

In particular, for those not familiar with it, note that you don't incorporate the word 'get' into a call to a getter (and similarly for setters):

var myBar = myFoo.getBar(); // wrong    
var myBar = myFoo.get('bar');  // wrong

You should simply do this:

var myBar = myFoo.bar;  // correct (get)
myFoo.bar = true;  // correct (set) (false is correct too obviously!)

given a class like:

class foo {
  private _bar:boolean = false;

  get bar():boolean {
    return this._bar;
  }
  set bar(theBar:boolean) {
    this._bar = theBar;
  }
}

then the 'bar' getter for the private '_bar' property will be called.


TS offers getters and setters which allow object properties to have more control of how they are accessed (getter) or updated (setter) outside of the object. Instead of directly accessing or updating the property a proxy function is called.

Example:

class Person {
    constructor(name: string) {
        this._name = name;
    }

    private _name: string;

    get name() {
        return this._name;
    }

    // first checks the length of the name and then updates the name.
    set name(name: string) {
        if (name.length > 10) {
            throw new Error("Name has a max length of 10");
        }

        this._name = name;  
    }

    doStuff () {
        this._name = 'foofooooooofoooo';
    }


}

const person = new Person('Willem');

// doesn't throw error, setter function not called within the object method when this._name is changed
person.doStuff();  

// throws error because setter is called and name is longer than 10 characters
person.name = 'barbarbarbarbarbar';  

It is very similar to creating common methods, simply put the keyword reserved get or set at the beginning.

class Name{
    private _name: string;

    getMethod(): string{
        return this._name;
    }

    setMethod(value: string){
        this._name = value
    }

    get getMethod1(): string{
        return this._name;
    }

    set setMethod1(value: string){
        this._name = value
    }
}

class HelloWorld {

    public static main(){

        let test = new Name();

        test.setMethod('test.getMethod() --- need ()');
            console.log(test.getMethod());

        test.setMethod1 = 'test.getMethod1 --- no need (), and used = for set ';
            console.log(test.getMethod1);
    }
}
HelloWorld.main();

In this case you can skip return type in get getMethod1() {

    get getMethod1() {
        return this._name;
    }

If you are working with TypeScript modules and are trying to add a getter that is exported, you can do something like this:

// dataStore.ts
export const myData: string = undefined;  // just for typing support
let _myData: string;  // for memoizing the getter results

Object.defineProperty(this, "myData", {
    get: (): string => {
        if (_myData === undefined) {
            _myData = "my data";  // pretend this took a long time
        }

        return _myData;
    },
});

Then, in another file you have:

import * as dataStore from "./dataStore"
console.log(dataStore.myData); // "my data"

Here's a working example that should point you in the right direction:

class Foo {
    _name;

    get Name() {
        return this._name;
    }

    set Name(val) {
        this._name = val;
    }
}

Getters and setters in JavaScript are just normal functions. The setter is a function that takes a parameter whose value is the value being set.