A subclass derives from another class with `extends`. Use one when a new class needs the existing class’s behavior but must add or specialize features. If the subclass declares a constructor, it must call the superclass constructor with `super(...)` so inherited properties are initialized. section 11.3.7
Extend a class
In `src/index.ts`, `class Employee extends Person` calls `super(id, name, city)` in its constructor, then adds a department and a `writeDept()` method. The shared `Person` properties remain available alongside the employee-specific behavior. section 11.3.7
Do not assume an array’s inferred type records the superclass you have in mind. An array containing an `Employee` and a `Customer` can be inferred as `(Employee | Customer)[]`; adding a different `Person` subclass may then fail. Declare `let data: Person[]` when the array should accept any of those subclasses. TypeScript checks object shapes when resolving the inferred type. section 11.3.7
Listing 11.19 Using a type annotation in the index.ts file in the src folder
...
let data: Person[] = [new Employee("fvega", "Fidel Vega", "Sales",
"Paris"), new Customer("ajones", "Alice Jones", "London", 500)];
data.push(new Supplier("dpeters", "Dora Peters", "New York", "Acme"));
...
See the explicit `Person[]` annotation that lets the array accept several subclasses. section 11.3.7
Add persistent storage without replacing the collection API
In `src/todoCollection.ts`, changing `itemMap` to `protected` lets subclasses access it while keeping it unavailable to unrelated code. In `src/jsonTodoCollection.ts`, `JsonTodoCollection extends TodoCollection` calls `super(userName, [])`, then uses Lowdb to read tasks from `Todos.json` or initialize the file from supplied items. The application can hold the result as `let collection: TodoCollection = new JsonTodoCollection("Adam", todos);`. section 2.5
Subclasses can also complete an abstract class: `ArrayCollection<T>` supplies `add` and `count`, while its `ProductCollection` and `PersonCollection` subclasses implement the abstract `get` method for their respective types. A class decorator can instead return a subclass to add a method, but that method does not automatically appear in the decorated class’s TypeScript type; an interface and type guard provide type-safe access. section 12.4.2 section 14.3.1
Listing 12.26 Defining an abstract class in the index.ts file in the src folder
import { City, Person, Product, Employee } from "./dataTypes.js";
type shapeType = { name: string };
interface Collection<T extends shapeType> {
add(...newItems: T[]): void;
get(name: string): T;
count: number;
}
abstract class ArrayCollection<T extends shapeType>
implements Collection<T> {
protected items: T[] = [];
add(...newItems: T[]): void {
this.items.push(...newItems);
}
abstract get(searchTerm: string): T;
get count(): number {
return this.items.length;
}
}
class ProductCollection extends ArrayCollection<Product> {
get(searchTerm: string): Product {
return this.items.find(item => item.name === searchTerm);
}
}
class PersonCollection extends ArrayCollection<Person> {
get(searchTerm: string): Person {
return this.items.find(item =>
item.name === searchTerm || item.city === searchTerm);
}
}
let peopleCollection: Collection<Person> = new PersonCollection();
peopleCollection.add(new Person("Bob Smith", "London"),
new Person("Dora Peters", "New York"));
let productCollection: Collection<Product> = new ProductCollection();
productCollection.add(new Product("Running Shoes", 100),
new Product("Hat", 25));
[peopleCollection, productCollection].forEach(c =>
console.log(`Size: ${c.count}`));
Compare the abstract collection’s shared implementation with the `get` methods supplied by its subclasses. section 12.4.2

