Classes, Deep
private มีสองแบบ
หัวข้อที่มีชื่อว่า “private มีสองแบบ”TypeScript มีสองวิธีทำให้ member เป็น private และทั้งสองไม่เหมือนกัน
class Account { private balance = 0; // compile-time only — erased #pin = "1234"; // truly private — enforced at runtime
check() { return this.balance + Number(this.#pin); }}
const a = new Account();// a.balance; // ❌ compile error, but...// (a as any).balance; // ✅ reachable at runtime — private was erased// a.#pin; // ❌ SyntaxError even at runtime — hard privateprivate(และprotected) เป็น access check ตอน compile time และถูก erase ตอน emit ดังนั้นคนที่ตั้งใจจริงยังเข้าถึง field ตอน runtime ได้ผ่านanyหรือ bracket access modifier พวกนี้บอก intent และจับ mistake ที่ตั้งใจดี- field
#nameเป็น ECMAScript private field — เข้าถึงจากนอก class ไม่ได้จริง ๆ บังคับโดย JavaScript engine เอง ใช้#เมื่อ privacy ต้อง hold ตอน runtime
protected อยู่ตรงกลาง: เข้าถึงได้ใน class และ subclass ของตัวเอง แต่ไม่ได้จากข้างนอก
readonly field
หัวข้อที่มีชื่อว่า “readonly field”readonly อนุญาตให้ assign ได้แค่ตอน declaration หรือใน constructor แล้ว lock field นั้น เหมือน private เป็น compile-time guarantee — ถูก erase ตอน runtime
class Point { readonly x: number; constructor(x: number) { this.x = x; // ✅ allowed in the constructor } move() { // this.x = 5; // ❌ Cannot assign to 'x' because it is read-only. }}parameter property: constructor shorthand
หัวข้อที่มีชื่อว่า “parameter property: constructor shorthand”การ declare field แล้ว assign จาก constructor parameter เกิดบ่อยมากจน TypeScript มี shorthand: ใส่ access modifier บน constructor parameter แล้ว parameter นั้นจะกลายเป็น field อัตโนมัติ
class User { constructor( public readonly id: string, private name: string, ) {} // No separate field declarations, no `this.id = id` — the modifiers do it.}อันนี้เท่ากับการ declare id และ name เป็น field แล้ว assign ใน body เป็นแค่ความสะดวก แต่เป็นความสะดวกที่ใช้กันกว้างขวาง
static member
หัวข้อที่มีชื่อว่า “static member”static member เป็นของ ตัว class เอง ไม่ใช่ของ instance มีอยู่จริงตอน runtime เป็น property บน constructor function
class Circle { static readonly PI = 3.14159; static area(r: number) { return Circle.PI * r * r; }}
Circle.area(2); // called on the class, not an instanceabstract class
หัวข้อที่มีชื่อว่า “abstract class”abstract class instantiate ตรง ๆ ไม่ได้ มีไว้ให้ extend abstract method declare signature ที่ subclass ต้อง implement ตัว marker abstract เป็น compile-time only
abstract class Shape { abstract area(): number; // no body — subclasses must provide one describe() { return `area is ${this.area()}`; } // concrete method}
// new Shape(); // ❌ Cannot create an instance of an abstract class.
class Square extends Shape { constructor(private side: number) { super(); } area() { return this.side * this.side; } // required}implements เป็นการเช็ค ไม่ใช่ inheritance
หัวข้อที่มีชื่อว่า “implements เป็นการเช็ค ไม่ใช่ inheritance”class implements interface ได้ อันนี้ ไม่ได้ copy อะไรเข้ามา — เป็น assertion ตอน compile time ว่า class satisfy interface เชิง structural เพราะ TypeScript เป็น structural class match interface ได้ โดยไม่ต้อง implements clause แค่ทำให้ intent ชัดเจนและเปลี่ยน mismatch ให้เป็น error ที่จุดนิยาม class แทนที่จะเป็นที่จุดใช้งาน
interface Named { name: string; }
class Product implements Named { name = "widget"; // if this were missing, the error points HERE}