← Back to TypeScript Menu | 🏠 Hub
class User {
// Properties with types
id: number;
name: string;
email: string;
private password: string; // private — outside ကနေ access မရ
protected role: string; // protected — subclass access ရ
readonly createdAt: Date; // readonly — after init မပြောင်းရ
constructor(id: number, name: string, email: string, password: string) {
this.id = id;
this.name = name;
this.email = email;
this.password = password;
this.role = "user";
this.createdAt = new Date();
}
// Method
greet(): string {
return `Hello, I'm ${this.name}`;
}
// Getter (property-like access)
get displayName(): string {
return `${this.name} (${this.role})`;
}
// Setter
set newPassword(pwd: string) {
if (pwd.length < 8) throw new Error("Too short!");
this.password = pwd;
}
}
const user = new User(1, "Ko Ko", "ko@test.com", "pass1234");
console.log(user.name); // "Ko Ko" ✅
console.log(user.password); // ❌ Error: private!
console.log(user.displayName); // "Ko Ko (user)"
// TypeScript shortcut: access modifier in constructor params
class Product {
constructor(
public readonly id: number,
public name: string,
public price: number,
private stock: number = 0
) {}
// → automatically creates and assigns: this.id, this.name, this.price, this.stock
// No need to declare properties or assign in body!
isInStock(): boolean { return this.stock > 0; }
addStock(qty: number): void { this.stock += qty; }
}
const laptop = new Product(1, "Laptop", 1200, 10);
console.log(laptop.name); // "Laptop"
console.log(laptop.stock); // ❌ private!
interface Serializable {
serialize(): string;
toJSON(): object;
}
class BaseEntity {
constructor(public id: number, public createdAt: Date = new Date()) {}
toString(): string { return `Entity(${this.id})`; }
}
class User extends BaseEntity implements Serializable {
constructor(
id: number,
public name: string,
public email: string,
protected role: "admin" | "user" = "user"
) {
super(id); // ← call parent constructor!
}
serialize(): string { return JSON.stringify(this.toJSON()); }
toJSON() {
return { id: this.id, name: this.name, email: this.email, role: this.role };
}
}
class AdminUser extends User {
constructor(id: number, name: string, email: string, public permissions: string[]) {
super(id, name, email, "admin");
}
hasPermission(perm: string): boolean {
return this.permissions.includes(perm);
}
}
const admin = new AdminUser(1, "Ko Ko", "ko@test.com", ["read", "write", "delete"]);
console.log(admin.hasPermission("delete")); // true
console.log(admin.serialize());
// Abstract = cannot instantiate directly, must be subclassed
abstract class Repository<T> {
abstract findAll(): Promise<T[]>;
abstract findById(id: number): Promise<T | null>;
abstract create(data: Partial<T>): Promise<T>;
abstract update(id: number, data: Partial<T>): Promise<T>;
abstract delete(id: number): Promise<boolean>;
// Concrete method (shared by all)
async exists(id: number): Promise<boolean> {
const item = await this.findById(id);
return item !== null;
}
}
interface User { id: number; name: string; email: string; }
class UserRepository extends Repository<User> {
private users: User[] = [];
async findAll() { return this.users; }
async findById(id: number) { return this.users.find(u => u.id === id) || null; }
async create(data: Omit<User, 'id'>) {
const user = { id: this.users.length + 1, ...data };
this.users.push(user);
return user;
}
async update(id: number, data: Partial<User>) {
const idx = this.users.findIndex(u => u.id === id);
this.users[idx] = { ...this.users[idx], ...data };
return this.users[idx];
}
async delete(id: number) {
const idx = this.users.findIndex(u => u.id === id);
if (idx === -1) return false;
this.users.splice(idx, 1);
return true;
}
}
const repo = new UserRepository();
await repo.create({ name: "Ko Ko", email: "ko@test.com" });
← TS 03 | Next: TS 05 → Generics →