Question
I am trying to create getter and setter methods for a property in TypeScript.
private _name: string;
Name() {
get: {
return this._name;
}
set: {
this._name = ???;
}
}
What is the correct syntax for defining a getter and setter, and what value does the setter receive?
Short Answer
By the end of this page, you will understand how to define getters and setters in TypeScript, how setter parameters work, and how accessors are used like normal properties rather than regular methods.
Concept
In TypeScript, getters and setters are special class members called accessors. They let you control how a property is read and updated.
A getter runs when code reads a property. A setter runs when code assigns a value to a property.
This is useful because you can:
- hide internal fields such as
_name - validate values before saving them
- compute values dynamically
- keep a simple property-style API for users of your class
In TypeScript, getters and setters are declared with the get and set keywords directly on class members. They are not written inside another method.
A setter receives the new assigned value as a parameter. You choose the parameter name.
For example:
class Person {
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
}
Here:
get name()returns the current valueset name(value: string)receives the new value in thevalueparameter
This matters in real programming because many classes need to protect their internal state. Instead of letting outside code directly change fields in unsafe ways, accessors give you a controlled entry point.
Mental Model
Think of a class like a building with a reception desk.
- The private field
_nameis a file stored in a back office. - The getter is the receptionist who fetches the file when someone asks for it.
- The setter is the receptionist who checks and stores a new file when someone delivers one.
Outside code does not touch the back office directly. It talks to the receptionist through the property.
That means you can later add rules, such as:
- reject empty names
- trim extra spaces
- log changes
without changing how other code uses the property.
Syntax and Examples
Basic syntax
class Person {
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
}
Using the accessor
const person = new Person();
person.name = "Ava"; // calls the setter
console.log(person.name); // calls the getter
Even though name uses get and set, you use it like a normal property.
Example with validation
class Person {
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
if (value.trim() === "") {
throw new Error("Name cannot be empty");
}
this._name = value.trim();
}
}
const person = new Person();
person.name = " Maya ";
console.log(person.name); // "Maya"
This example shows why accessors are useful: the setter can clean and validate input before storing it.
Step by Step Execution
Consider this code:
class Person {
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
}
const person = new Person();
person.name = "Leo";
console.log(person.name);
Step by step:
-
const person = new Person();- A new
Personobject is created. _namestarts as"".
- A new
-
person.name = "Leo";- This does not directly assign to a public field.
- It calls the setter:
set name(value: string). - Inside the setter,
valueis"Leo". - The setter runs
this._name = value;. _nameis now"Leo".
-
console.log(person.name);- This calls the getter:
get name(): string. - The getter returns
this._name. - The printed result is
Leo.
- This calls the getter:
Tiny trace
| Line | Action | Result |
|---|---|---|
new Person() | Create object | _name = "" |
person.name = "Leo" | Call setter | _name = "Leo" |
person.name | Call getter | returns "Leo" |
Real World Use Cases
Getters and setters are common when a class should expose a clean property API while controlling internal data.
Common use cases
- Form models: trim and validate user input before saving it
- Configuration objects: reject invalid settings
- API response wrappers: transform raw data into cleaner values
- Domain models: enforce business rules such as age must be positive
- Computed properties: return a value based on other fields
Example: validating configuration
class AppConfig {
private _port: number = 3000;
get port(): number {
return this._port;
}
set port(value: number) {
if (value < 1 || value > 65535) {
throw new Error("Invalid port number");
}
this._port = value;
}
}
This lets the rest of the app use config.port naturally, while still enforcing rules.
Real Codebase Usage
In real projects, developers often use getters and setters for encapsulation and validation, but usually only when there is a clear reason. If a property needs no custom logic, a normal public field may be simpler.
Common patterns
Validation in setters
set email(value: string) {
if (!value.includes("@")) {
throw new Error("Invalid email address");
}
this._email = value;
}
Normalizing values
set username(value: string) {
this._username = value.trim().toLowerCase();
}
Read-only computed getter
class Rectangle {
constructor(public width: number, public height: number) {}
get area(): number {
return this.width * this.height;
}
}
Backing field convention
Developers often store the real value in a private field such as:
_name_email_port
and expose a cleaner public accessor such as:
nameemailport
When not to use them
Avoid getters and setters when they add no value. If your code just stores and returns a value with no validation or transformation, a public property may be enough.
Common Mistakes
1. Writing accessors inside a method
This is invalid:
class Person {
private _name: string = "";
Name() {
get: {
return this._name;
}
set: {
this._name = ???;
}
}
}
Getters and setters must be declared as class members:
class Person {
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
}
2. Forgetting the setter parameter
Broken:
set name() {
this._name = value;
}
Correct:
set name(value: string) {
this._name = value;
}
3. Calling an accessor like a method
Broken:
person.name("Ava");
console.log(person.name());
Correct:
person.name = "Ava";
console.log(person.name);
4. Accidentally causing infinite recursion
Broken:
class Person {
set name(value: string) {
this.name = value; // calls the setter again and again
}
}
Correct:
class Person {
private _name: string = "";
set name(value: string) {
this._name = value;
}
}
5. Using different types for getter and setter carelessly
Keep the API clear and consistent unless you have a strong reason not to.
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
Comparisons
| Concept | How it is used | Best for |
|---|---|---|
| Public property | person.name = "Ava" | Simple storage with no extra logic |
| Getter and setter | person.name = "Ava", person.name | Validation, formatting, controlled access |
| Regular methods | person.setName("Ava"), person.getName() | Explicit actions or when property syntax is not desired |
Getter/setter vs traditional methods
class PersonWithMethods {
private _name: string = "";
getName(): string {
return this._name;
}
setName(value: string) {
this._name = value;
}
}
class PersonWithAccessors {
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
}
Accessors usually feel more natural because they are used like properties.
private _name vs public name
private _namestores the actual internal data.nameexposes a safe public interface.
That separation helps you change the internal implementation later without changing outside code.
Cheat Sheet
Basic syntax
class Example {
private _value: string = "";
get value(): string {
return this._value;
}
set value(newValue: string) {
this._value = newValue;
}
}
Usage
const e = new Example();
e.value = "hello"; // setter
console.log(e.value); // getter
Rules
- Use
get propertyName()to define a getter. - Use
set propertyName(parameter)to define a setter. - The setter receives the assigned value as its parameter.
- Accessors are declared directly in the class, not inside another method.
- Use accessors like properties, not like function calls.
- Use a private backing field such as
_nameto avoid recursion.
Common pattern
private _name: string = "";
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
Watch out for
this.name = valueinsideset name(...)causes recursionperson.name()is wrong for an accessor- A setter must have exactly one parameter
FAQ
What is the parameter name in a TypeScript setter?
You choose the name yourself. Common choices are value, newValue, or something descriptive like name.
Do I need both a getter and a setter?
No. You can define only a getter for read-only access, or both if the property should be writable.
How do I call a getter in TypeScript?
You do not call it like a method. Use property access:
console.log(person.name);
How do I call a setter in TypeScript?
Assign to the property:
person.name = "Ava";
Why use _name instead of name internally?
Because the accessor is already named name. Using _name avoids calling the getter or setter recursively.
Can a getter compute a value instead of returning a stored field?
Yes. A getter can calculate and return a value each time it is accessed.
Are getters and setters the same as normal methods?
No. They look like methods in class syntax, but they are used like properties.
Mini Project
Description
Build a small UserProfile class that stores a username safely. The project demonstrates how to use a private backing field with a getter and setter, and how to validate input before saving it.
Goal
Create a class whose username property can be read and updated safely using TypeScript accessors.
Requirements
- Create a class named
UserProfile. - Store the real value in a private field.
- Add a getter named
usernamethat returns the current username. - Add a setter named
usernamethat rejects empty values. - Trim whitespace before saving the username.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.