<Demopeu/>

TS에서의 클래스(Class)

TS에서의 클래스(Class)

referencetypescriptclassaccess-modifiers

📌 JavaScript에서의 class

class Student {
    // 필드
    name;
    age;

    //생성자
    constructor(name, age){
        this.name = name;
        this.age = age;
    }

    // 메서드
    study() {
        console.log(`${this.name} is studying.`);
    }
}
  1. 필드 : 이 클래스가 생성할 객체가 갖은 프로퍼티
  2. 생성자 : 실질적으로 객체를 생성하는 특수한 메서드, new 클래스이름형태로 클래스의 생성자 함수 호출.
    const studentB = new Student("홍길동", 27);
    
  3. 메서드 : 클래스가 생성할 객체가 갖는 함수
  4. this : 생성된 객체 자신을 가리키는 키워드
  5. 상속 : 다른 클래스의 필드와 메서드를 물려받는 기능
    class StudentDeveloper extends Student {
        // 필드
        favoriteSkill;
    
        // 생성자
        constructor(name, age, favoriteSkill) {
            super(name, age); // 부모 클래스의 생성자 호출
            this.favoriteSkill = favoriteSkill;
        }
    
        // 메서드
        programming() {
            console.log(`${this.favoriteSkill}로 프로그래밍 함`);
        }
    }
    

JS에서 클래스의 특징

  1. 클래스는 함수로 정의되지만, 호이스팅될 때 초기화되지 않음
  2. 클래스의 body는 strict mode로 실행됨
  3. constructor 메서드는 무조건 하나만 있을 수 있음
  4. getter/setter : obj.prop 읽을 때 자동으로 호출되는 함수/obj.prop = 값 대입할 때 자동으로 호출되는 함수
  5. static : 정적(static) 메서드를 정의
   class Point {
       constructor(x, y) {
           this.x = x;
           this.y = y;
       }

       static displayName = "Point";
       static distance(a, b) {
           const dx = a.x - b.x;
           const dy = a.y - b.y;

           return Math.hypot(dx, dy);
       }
   }

   const p1 = new Point(5, 5);
   const p2 = new Point(10, 10);
   p1.displayName; // undefined
   p1.distance; // undefined
   p2.displayName; // undefined
   p2.distance; // undefined

  console.log(Point.displayName); // "Point"
   console.log(Point.distance(p1, p2)); // 7.0710678118654755
  1. 필드선언 : 클래스 본문 안에서 인스턴스가 가질 값을 미리 선언하는 문법
    기존에는 constructor 안에서 this.foo = ... 형식으로 프로퍼티를 만들었지만, 이제는 클래스 정의 안에서 바로 public/ private 필드를 선언할 수 있다.
class Person {
 name = 'Kim';   // public 필드
 #age = 20;      // private 필드 (클래스 내부에서만 접근 가능)

 introduce() {
   console.log(this.name);   // O
   console.log(this.#age);   // O
 }
}

const p = new Person();
console.log(p.name);  // 'Kim'
console.log(p.#age);  // 에러: private 필드는 외부에서 접근 불가

현재 public/#private 필드 문법은 공식 표준에 포함되어 있고, 최신 브라우저와 Node.js에서 기본 지원

📌 TypeScript에서의 클래스

💡 접근 제어자(access modifiers)

1. public

기본값으로, 어디서든 접근 가능. 생략하면 public으로 간주됨.

2. private

private로 선언된 프로퍼티는 클래스 내부에서만 접근 가능.
readonly와 다르게 읽기조차 불가능.
심지어 상속받은 자식 클래스에서도 접근할 수 없다.

    class Student {
        private name: string;
        private age: number;
        protected favoriteSkill: string;

        constructor(name: string, age: number, favoriteSkill: string) {
            this.name = name;
            this.age = age;
            this.favoriteSkill = favoriteSkill;
        }
    }

    class StudentDeveloper extends Student {
        constructor(name: string, age: number, favoriteSkill: string) {
            super(name, age, favoriteSkill);
        }

        programming() {
            console.log(`${this.name} is programming.`); // ❌ Error: 'name'속성은 private이며 'Student' 클래스 내에서만 엑세스 할 수 있습니다.
        }
    }

3. protected

protected로 선언된 프로퍼티는 클래스 내부와 자식 클래스에서만 접근 가능.
private와 다르게 상속받은 자식 클래스에서 접근할 수 있다.

생성자에서 접근 제어자 사용시

class Student {
    constructor(
        public name: string,
        public age: number,
        protected favoriteSkill: string,
    ) {}
}
  • 생성자 인자로 선언하면 필드를 생략해야하며, 접근 제어자를 생략할 수 있다.

💡 implements

implements는 인터페이스를 구현하는 클래스를 정의할 때 사용한다.

interface Student {
    name: string;
    age: number;
}

class StudentDeveloper implements Student {
    name: string;
    age: number;

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
}

여기서 주의할 점은 인터페이스는 무조건 public으로 선언되어있기 때문에 필드나 생성자에 private, protected로 선언할 수 없다.


TypeScript에서 클래스는 타입으로도 사용할 수 있다?

    class Student {
        name: string;
        age: number;
    }
    const student: Student = {
        name: "홍길동",
        age: 20,
    };
  • TypeScript는 구조적 타입 시스템을 따르기 때문이다.