adplus-dvertising

get and set in TypeScript

Asked 10 years ago
Viewed 765.92 k times

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?

asked 10 years ago

Correct Answer

TypeScript uses getter/setter syntax that is like ECMAScript4/ActionScript3.

class foo {
    private _bar: boolean = false;
    get bar(): boolean {
        return this._bar;
    }
    set bar(value: boolean) {
        this._bar = value;
    }
}

That will produce this JavaScript, using the ECMAScript 5 Object.defineProperty() feature.

var foo = (function () {
    function foo() {
        this._bar = false;
    }
    Object.defineProperty(foo.prototype, "bar", {
        get: function () {
            return this._bar;
        },
        set: function (value) {
            this._bar = value;
        },
        enumerable: true,
        configurable: true
    });
    return foo;
})();

So to use it,

var myFoo = new foo();
if(myFoo.bar) {         // calls the getter
    myFoo.bar = false;  // calls the setter and passes false
}

However, in order to use it at all, you must make sure the TypeScript compiler targets ECMAScript5. If you are running the command line compiler, use --target flag like this;

tsc --target ES5

If you are using Visual Studio, you must edit your project file to add the flag to the configuration for the TypeScriptCompile build tool. You can see that here:

As @DanFromGermany suggests below, if your are simply reading and writing a local property like foo.bar = true, then having a setter and getter pair is overkill. You can always add them later if you need to do something, like logging, whenever the property is read or written.

Getters can be used to implement readonly properties. Here is an example that also shows how getters interact with readonly and optional types.

//
// type with optional readonly property.
// baz?:string is the same as baz:string|undefined
//
type Foo = {
    readonly bar: string;
    readonly baz?: string;
}
const foo:Foo = {bar: "bar"}
console.log(foo.bar) // prints 'bar'
console.log(foo.baz) // prints undefined

//
// interface with optional readonly property
//
interface iFoo {
    readonly bar: string;
    readonly baz?: string;
}

const ifoo:iFoo = {bar: "bar"}
console.log(ifoo.bar)  // prints 'bar'
console.log(ifoo.baz)  // prints undefined


//
// class implements bar as a getter, 
// but leaves off baz.
//
class iBarClass implements iFoo {

    get bar() { return "bar" }
}
const iBarInstance = new iBarClass()
console.log(iBarInstance.bar) // prints 'bar'
console.log(iBarInstance.baz) // prints 'undefined'
// accessing baz gives warning that baz does not exist 
// on iBarClass but returns undefined
// note that you could define baz as a getter
// and just return undefined to remove the warning.


//
// class implements optional readonly property as a getter
//
class iBazClass extends iBarClass {
    private readonly _baz?: string

    constructor(baz?:string) {
        super()
        this._baz = baz
    }

    get baz() { return this._baz; }
}

const iBazInstance = new iBazClass("baz")
console.log(iBazInstance.bar)  // prints bar
console.log(iBazInstance.baz)  // prints baz
answered 10 years ago

Other Answer

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.

answered 10 years ago