乐闻世界logo
搜索文章和话题

How to use get and set in typescript

5 个月前提问
3 个月前修改
浏览次数57

6个答案

1
2
3
4
5
6

在TypeScript中,getset访问器允许我们有效地封装对象中的属性,通过这种方式可以在读取或写入属性时执行额外的逻辑。get访问器用于定义如何读取属性值,而set访问器则定义如何设置属性值。下面是一个使用getset访问器的例子:

typescript
class Person { private _firstName: string; private _lastName: string; constructor(firstName: string, lastName: string) { this._firstName = firstName; this._lastName = lastName; } // 使用 get 访问器来读取 fullName get fullName(): string { return `${this._firstName} ${this._lastName}`; } // 使用 set 访问器来设置 firstName 和 lastName set fullName(name: string) { const parts = name.split(' '); if (parts.length !== 2) { throw new Error('请输入一个完整的名字,例如:John Doe'); } this._firstName = parts[0]; this._lastName = parts[1]; } } let person = new Person('John', 'Doe'); // 通过 get 访问器获取 fullName console.log(person.fullName); // 输出: John Doe // 通过 set 访问器修改 fullName person.fullName = 'Jane Smith'; // 再次通过 get 访问器获取修改后的 fullName console.log(person.fullName); // 输出: Jane Smith

在上述例子中,Person 类有两个私有属性 _firstName_lastName。为了能够控制对这些属性的访问,我们定义了一个 fullName 属性,它有一个 get 访问器和一个 set 访问器。

  • get fullName() 方法用于在需要时构造并返回一个完整的名字,即 _firstName_lastName 的组合。
  • set fullName(name: string) 方法允许我们通过一个字符串来设置 _firstName_lastName。如果传入的字符串不是两个部分组成,则会抛出错误。

这样,我们就可以用面向对象的方式,封装属性的具体实现细节,同时通过访问器提供简单的接口供外部代码使用。这样做的好处是可以在设置和获取属性时添加验证逻辑或其他附加操作,而不必暴露类的内部结构。

2024年6月29日 12:07 回复

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

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

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

shell
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:

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

shell
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; })();

More recent versions of EcmaScript will produce code that looks more like the original TypeScript. For instance, targeting EcmaScript2017 will produce:

shell
"use strict"; class foo {     constructor() {         this._bar = false;     }     get bar() {         return this._bar;     }     set bar(value) {         this._bar = value;     } }

So to use it,

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

As @DanFromGermany suggests below, if you 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.

shell
// // 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
2024年6月29日 12:07 回复

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):

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

You should simply do this:

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

given a class like:

shell
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.

2024年6月29日 12:07 回复

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

shell
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.

2024年6月29日 12:07 回复

You can write this

shell
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; } }
2024年6月29日 12:07 回复

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:

shell
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 :

shell
function () { return this.tiresCount; }

and the setter is :

shell
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.
2024年6月29日 12:07 回复

你的答案