Specify Access Modifiers for TypeScript Class Members
Monday, November 11, 2019
Specify Access Modifiers for TypeScript Class Members
It is important to understand and to specify access modifiers for TypeScript class members.
First, public
is the default access. That means that any properties or methods in your class that do not specify an access modifier are publicly available to consumers of the class. A public property or method should be considered the API to the class, and ideally, should not be open for modification.
Private properties and methods use the private
access modifier prior to the property or method name. This denotes that the property or method is internal to the class, and should not be accessed by consumers of the class. This also means that the private property and method names and signatures can be modified as necessary.
Protected properties and methods use the protected
access modifier prior to the property or method name. This denotes that the property or method is internal to the class, as well as all classes that extend, and thus inherit the parent class's functionality. The protected access modifier enables developers to build classes that are closed for modification, but are open to extension. Specific implementations and future feature classes can extend the class to modify the behavior of the class, or to add additional functionality.
It is important to not simply leave off access modifiers for all class members, as this leaves the class surface open to consumers of the class to expect that all properties and methods are stable and will not be modified in the future.
The key takeaway is: only leave class members open to the public if they are intentionally meant for the public. And, if the class member is intended to be public, you can use the shorthand syntax or not specifying the access modifier since public
is the default.
Instructions
not specify the access modifier when the class member is public
specify either the private
or protected
access modifier as necessary
leaving all class members as public
starting with the private
access modifier for class members that may not necessarily be publicly accessible, and then implement protected
on a case-by-case basis
classes should be closed for modification but open for extension
defaulting all class members to public could expose properties and methods to consumers that are not intended to be used
Code Examples
Specify the private
and protected
access modifiers
import { Contribution } from './contribution.model';
import { ContributionService } from '../services/contribution.service';
export class User {
/** Get the number of contributions for this user. */
public get contributionCount(): number {
return this.getContributions().length;
}
/** The user-friendly display name of the user. */
public displayName: string;
/** The user's email address. */
public email: string;
/** Access details. */
private access: { admin: boolean, editor: boolean };
constructor(data: { [ key: string]: any }) {
Object.assign(this, data);
}
/** Returns true if the user can edit contributions. */
public canEdit(): boolean {
return this.access && (this.access.admin || this.access.editor);
}
/** Get the contributions for the current user. */
protected getContributions(): Contribution[] {
return ContributionService.contributionsByUser(this);
}
}
Prefer short-hand syntax and drop the public
access modifiers
import { Contribution } from './contribution.model';
import { ContributionService } from '../services/contribution.service';
export class User {
/** Prefer short-hand syntax and drop the `public` access modifiers. */
public get contributionCount(): number {
return this.getContributions().length;
}
/** Prefer short-hand syntax and drop the `public` access modifiers. */
public displayName: string;
/** Prefer short-hand syntax and drop the `public` access modifiers. */
public email: string;
/** Access details. */
private access: { admin: boolean, editor: boolean };
constructor(data: { [ key: string]: any }) {
Object.assign(this, data);
}
/** Prefer short-hand syntax and drop the `public` access modifiers. */
public canEdit(): boolean {
return this.access && (this.access.admin || this.access.editor);
}
/** Get the contributions for the current user. */
protected getContributions(): Contribution[] {
return ContributionService.contributionsByUser(this);
}
}
All class members are public
import { Contribution } from './contribution.model';
import { ContributionService } from '../services/contribution.service';
export class User {
/** Prefer short-hand syntax and drop the `public` access modifiers. */
get contributionCount(): number {
return this.getContributions().length;
}
/** Prefer short-hand syntax and drop the `public` access modifiers. */
displayName: string;
/** Prefer short-hand syntax and drop the `public` access modifiers. */
email: string;
/** Access details. */
access: { admin: boolean, editor: boolean };
constructor(data: { [ key: string]: any }) {
Object.assign(this, data);
}
/** Prefer short-hand syntax and drop the `public` access modifiers. */
public canEdit(): boolean {
return this.access && (this.access.admin || this.access.editor);
}
/** This should be private to the class. */
getContributions(): Contribution[] {
return ContributionService.contributionsByUser(this);
}
}
Have a question or comment?