From harness-claude
Guides TypeScript class patterns: abstract classes, private fields (#), access modifiers, implements vs extends for domain modeling, encapsulation, and inheritance.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Use abstract classes, private fields, access modifiers, and implements vs extends correctly
Guides on advanced TypeScript patterns like conditional types, discriminated unions, branded types, and builders for type-safe APIs, domain models, and state machines.
Guides writing reusable, type-safe functions, classes, and interfaces using TypeScript generics. Use for multi-type operations, utility functions preserving types, constraints like extends, and inference.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Use abstract classes, private fields, access modifiers, and implements vs extends correctly
implements (interface conformance) and extends (inheritance)class User {
readonly id: string;
name: string;
private email: string;
constructor(id: string, name: string, email: string) {
this.id = id;
this.name = name;
this.email = email;
}
getEmail(): string {
return this.email;
}
}
class User {
constructor(
readonly id: string,
public name: string,
private email: string
) {}
}
// Equivalent to the longer form above
public (default) — accessible everywhereprivate — accessible only within the class (TypeScript-only enforcement)protected — accessible within the class and subclasses#field — true private (JavaScript runtime enforcement, not just TypeScript)class Account {
#balance: number; // True private — not accessible even via type assertions
constructor(initial: number) {
this.#balance = initial;
}
get balance(): number {
return this.#balance;
}
}
abstract class Shape {
abstract area(): number;
abstract perimeter(): number;
describe(): string {
return `Area: ${this.area()}, Perimeter: ${this.perimeter()}`;
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
area(): number {
return Math.PI * this.radius ** 2;
}
perimeter(): number {
return 2 * Math.PI * this.radius;
}
}
implements for interface conformance:interface Serializable {
serialize(): string;
deserialize(data: string): void;
}
class Config implements Serializable {
constructor(private data: Record<string, string>) {}
serialize(): string {
return JSON.stringify(this.data);
}
deserialize(data: string): void {
this.data = JSON.parse(data);
}
}
extends vs implements:
extends — single inheritance, inherits implementationimplements — multiple interface conformance, no implementation inheritedinterface Loggable {
log(message: string): void;
}
interface Cacheable {
cache(): void;
}
class Service extends BaseService implements Loggable, Cacheable {
log(message: string): void {
/* ... */
}
cache(): void {
/* ... */
}
}
class IdGenerator {
private static counter = 0;
static next(): string {
return `id_${++IdGenerator.counter}`;
}
}
class Repository<T extends { id: string }> {
private items = new Map<string, T>();
save(item: T): void {
this.items.set(item.id, item);
}
find(id: string): T | undefined {
return this.items.get(id);
}
findAll(): T[] {
return [...this.items.values()];
}
}
const userRepo = new Repository<User>();
// Instead of: class UserService extends DatabaseService extends LoggingService
class UserService {
constructor(
private db: DatabaseService,
private logger: LoggingService
) {}
}
TypeScript classes compile to JavaScript classes (ES2015+) or constructor functions (ES5 target). They add type annotations, access modifiers, and abstract members on top of standard JavaScript class syntax.
private vs #private:
private — TypeScript compile-time only. The property is still accessible at runtime via (obj as any).field or obj['field']#private — JavaScript runtime enforcement. The property is truly inaccessible outside the class. Cannot be accessed even through reflectionAbstract classes vs interfaces:
override keyword (TypeScript 4.3+):
class Animal {
move(): void {
/* ... */
}
}
class Dog extends Animal {
override move(): void {
/* ... */
} // Error if parent method does not exist
}
Enable noImplicitOverride to require the override keyword on all overridden methods.
Trade-offs:
#private fields are truly private — but cannot be accessed in tests, which some teams dislikehttps://typescriptlang.org/docs/handbook/2/classes.html