ae-missing-getter
"The property ___ has a setter but no getter."
Remarks
TypeScript properties are conventionally used to indicate an API that behaves similar to reading or writing a variable. For example, style guides often recommend:
- property getters shouldn't perform expensive/complex operations
- property getters shouldn't cause observable side-effects (e.g. reading the property moves a stream pointer forwards)
- property getters should avoid throwing exceptions
In the same way, it would be strange to declare a property getter without a setter. After assigning a value to a variable, intuitively a developer would expect to be able to read the assigned value.
Consider this example:
/**
* Represents a book from the catalog.
* @public
*/
export class Book {
private _title: string = 'untitled';
/**
* Sets the title of the book.
*/
// Error: (ae-missing-getter) The property "title" has a setter but no getter.
public set title(value: string) {
this._title = value;
}
}
const book: Book = new Book();
book.title = 'The Hobbit';
console.log('The title: ' + book.title); // prints "The title: undefined"
The above behavior is counterintuitive. The missing setter is likely a mistake in the API design.
API Extractor reports the ae-missing-getter
error.
How to fix
The simplest solution is to implement the missing property getter. Note that the getter's documentation describes both operations; a property setter cannot have a doc comment:
/**
* Represents a book from the catalog.
* @public
*/
export class Book {
private _title: string = 'untitled';
/**
* Gets or sets the title of the book.
*/
public get title(): string {
return this._title;
}
public set title(value: string) {
this._title = value;
}
}
const book: Book = new Book();
book.title = 'The Hobbit';
console.log('Title: ' + book.title); // prints "Title: The Hobbit"
Alternatively, if your API really needs to be a unidirectional operation, you should design it as a method instead of a property:
/**
* Represents a book from the catalog.
* @public
*/
export class Book {
private _title: string = 'untitled';
/**
* Sets the title of the book.
*/
public setTitle(title: string): void {
this._title = title;
}
}
A pitfall involving "inherited" getters
If you choose to disable the
ae-missing-getter
validation, be careful with inherited properties: If a child class overrides a property by specifying the setter only, the getter will become undefined. Unlike some other languages, ECMAScriptget
andset
attributes comprise a single accessor property that is being overridden. See this playground link for an example.