
1. 상속
타입스크립트에서는 일반적인 객체지향 패턴을 사용할 수 있습니다.
클래스 기반 프로그래밍의 가장 기본적인 패턴 중 하나는 상속을 이용하여 이미 존재하는 클래스를 확장해 새로운 클래스를 만들 수 있다는 것입니다.
예제를 봅시다.
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
}
const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
타입이 추가된것을 제외하고 자바스크립트에서 보았던 클래스와 일치합니다. 이는 상속 기능을 보여주는 가장 기본적인 예제입니다.
여기서 조금 더 확장해보겠습니다.
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) {
super(name);
}
move(distanceInMeters = 5) {
console.log('Slithering...');
super.move(distanceInMeters);
}
}
class Horse extends Animal {
constructor(name: string) {
super(name);
}
move(distanceInMeters = 45) {
console.log('Galloping...');
super.move(distanceInMeters);
}
}
let sam = new Snake('Sammy the Python');
let tom: Animal = new Horse('Tommy the Palomino');
sam.move();
tom.move(34);
// Slithering...
// Sammy the Python moved 5m.
// Galloping...
// Tommy the Palomino moved 34m.
상속을 할 때 알아둬야할 것이 있습니다.
tom의 타입은 Animal 입니다. Horse는 Animal을 상속하였기 때문에 tom은 Horse값을 가지지만 Animal타입으로 선언이가능합니다.
하지만 아래 예제처름 만약 Horse에 추가되는 메서드가있다면 어떻게 될까요 ?
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Horse extends Animal {
constructor(name: string) {
super(name);
}
move(distanceInMeters = 45) {
console.log('Galloping...');
super.move(distanceInMeters);
}
speak( content: string) {
console.log({content})
}
}
let tom: Animal = new Horse('Tommy the Palomino');
tom.move(34);
tom.speak("hi")

위와 같이 에러가 발생합니다. 따라서 상속후에 추가적으로 메서드를 넣고자 한다면 이런식으로 타입을 정하면 안됩니다. 오히려 타입을 정하지 않으면 타입스크립트가 알아서 추론을 해줍니다.
위와 같이 자식 클래스에 부모 클래스 타입을 할당한다면 추가적인 메서드나 인자는 불가능하고 property 추가는 가능하다.
class Horse extends Animal {
save: number;
constructor(name: string) {
super(name);
this.save = 0;
}
move(distanceInMeters = 45) {
console.log('Galloping...');
this.save = distanceInMeters;
super.move(distanceInMeters);
}
}
let tom: Animal = new Horse('Tommy the Palomino');
tom.move(34);
2. Public, private, protected Member
타입스크립트에서는 특정 메서드나 properties가 클래스 외부의 코드에 표시되는 여부를 제어할 수 있습니다.
그것들을 제어하는 Member가 바로 Public, private, protected 위 3가지입니다.
class test {
public first : number;
private second : number;
protected third : number;
constructor() {
this.first = 1;
this.second = 2
this.third = 3
}
}
타입스크립트는 위와 같이 public, private, protected 3가지 Member가 있습니다.
각각이 무엇인지 배우기 전에 알아둬야할 것이 있습니다.
이 3가지는 타입스크립트에서만 유효합니다. 자바스크립트에서는 아예 표시 되지않습니다.

1) public
타입스크립트에서는 기본적으로 메서드나 property를 생성하면 public이 됩니다. 즉, 굳이 public을 해주지 않아도 기본값이 public 자동으로 된다는 소리입니다.
따라서 명확히 public이라는 것을 강조하고 싶을 때는 사용하셔도 됩니다.
class Animal {
public name: string;
public constructor(theName: string) { this.name = theName; }
public move(distanceInMeters: number) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
2) protected
protected는 자신이 선언된 클래스의 하위 클래스에서만 엑세스 할 수 있습니다.
class Greeter {
public greet() {
console.log("Hello, " + this.getName());
}
protected getName() {
return "hi";
}
}
class SpecialGreeter extends Greeter {
public howdy() {
// OK to access protected member here
console.log("Howdy, " + this.getName());
}
}
const g = new SpecialGreeter();
g.greet(); // OK
g.getName();
// ~~~~~~~~
// Property 'getName' is protected and only accessible within class 'Greeter' and its subclasses.
3) private
private는 protected와 비슷하지만 하위 클래스에서도 멤버에 대한 액세스를 허용하지 않습니다.
class Base {
private x = 0;
}
const b = new Base();
// Can't access from outside the class
console.log(b.x);
// Property 'x' is private and only accessible within class 'Base'.
class Derived extends Base {
showX() {
// Can't access in subclasses
console.log(this.x);
// Property 'x' is private and only accessible within class 'Base'.
}
}
4) 주의할 점
private , protected 유형 검사 중에 대괄호 표기법을 사용하여 액세스 할 수도 있습니다.
이는 유닛 테스트와 같은 것들에 대해 private 선언 필드를 잠재적으로 더 쉽게 액세스할 수 있게 만들지만, 결국 private , protected 는 엄격하게 제한하지 않고 soft 하게 제한한다는 뜻입니다.
class MySafe {
protected secretKey = 12345;
private secretKey2 = 6789;
}
const s = new MySafe();
// Not allowed during type checking
console.log(s.secretKey);
// Property 'secretKey' is protected and only accessible within class 'MySafe' and its subclasses.
console.log(s.secretKey2);
// Property 'secretKey2' is private and only accessible within class 'MySafe'.
// OK
console.log(s['secretKey']);
console.log(s['secretKey2']);
따라서 엄격하게 property를 제어하고 싶다면 자바스크립트에도 있고 타입스크립트에서도 지원하는 "#"(ECMAScript 비공개 필드)을 사용하면 좋습니다.
class MySafe {
#secretKey = 12345;
#secretKey2 = 6789;
getKey() {
return [this.#secretKey, this.#secretKey2];
}
}
const s = new MySafe();
console.log(s.getKey());
// [12345, 6789]
// Not allowed during type checking
console.log(s.secretKey);
// Property 'secretKey' is protected and only accessible within class 'MySafe' and its subclasses.
console.log(s.secretKey2);
// Property 'secretKey2' is private and only accessible within class 'MySafe'.
console.log(s['#secretKey']);
// Property '#secretKey' does not exist on type 'MySafe'
console.log(s['#secretKey2']);
// Property '#secretKey2' does not exist on type 'MySafe'
console.log(s['secretKey']);
// Property '#secretKey' does not exist on type 'MySafe'
console.log(s['secretKey2']);
// Property '#secretKey2' does not exist on type 'MySafe'
❗️ 악의적인 사용자로부터 클래스의 값을 보호해야 하는 경우 클로저, WeakMaps 또는 개인 필드와 같은 갈력한 런타임 프라이버시를 제공하는 매커니즘을 사용해야 합니다. 런타임 동안 private, protected는 property or 메서드를 완벽하게 보호하지 못합니다.
끝으로 간단하게 복습해보겠습니다.

3. Readonly 지정자
readonly 키워드를 사용하여 property를 읽기 전용으로 만들 수 있습니다. 읽기 전용 프로퍼티들은 선언 또는 생성자에서 초기화해야 합니다.
class Octopus {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 오류! name은 읽기전용 입니다.
4. 추상 클래스 (Abstract Classes)
추상 클래스는 다른 클래스들이 파생될 수 있는 기초 클래스입니다.
추상 클래스는 직접 인스턴스화할 수 없습니다.
추상 클래스는 인터페이스와 달리 멤버에 대한 구현 세부 정보를 포함할 수 있습니다.
abstract 키워드는 추상 클래스뿐만 아니라 추상 클래스 내에서 추상 메서드를 정의하는데 사용됩니다.
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log("roaming the earth...");
}
}
추상 클래스 내에서 추상으로 표시된 메서드는 구현을 포함하지 않으며 반드시 파생된 클래스에서 구현되어야 합니다.
추상 메서드는 인터페이스 메서드와 비슷한 문법을 공유합니다. 둘 다 메서드 본문을 포함하지 않고 메서드를 정의합니다.
그러나 추상 메서드는 반드시 abstract 키워드를 포함해야하며, 선택적으로 접근 지정자를 포함할 수 있습니다.
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log("Department name: " + this.name);
}
abstract printMeeting(): void; // 반드시 파생된 클래스에서 구현되어야 합니다.
}
class AccountingDepartment extends Department {
constructor() {
super("Accounting and Auditing"); // 파생된 클래스의 생성자는 반드시 super()를 호출해야 합니다.
}
printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10am.");
}
generateReports(): void {
console.log("Generating accounting reports...");
}
}
let department: Department; // 추상 타입의 레퍼런스를 생성합니다
department = new Department(); // 오류: 추상 클래스는 인스턴스화 할 수 없습니다
department = new AccountingDepartment(); // 추상이 아닌 하위 클래스를 생성하고 할당합니다
department.printName();
department.printMeeting();
department.generateReports(); // 오류: 선언된 추상 타입에 메서드가 존재하지 않습니다
5. 인터페이스 처럼 사용하기
클래스를 인터페이스 처럼 사용할 수 있습니다.
클래스 선언은 클래스의 인스턴스를 나타내는 타입과 생성자 함수라는 두 가지를 생성합니다.
클래스는 타입을 생성하기 때문에 인터페이스를 사용할 수 있는 동일한 위치에서 사용할 수 있습니다.
class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};
source
'Typescript > 개념' 카테고리의 다른 글
[Typescript] tsconfig.json 옵션 (0) | 2023.08.22 |
---|---|
[TypeScript] generics (0) | 2023.02.15 |
[Typescript] void (0) | 2023.02.14 |
[Typescript] 3. Polymorphism / generics (0) | 2023.01.19 |
[Typescript] declare (0) | 2022.12.28 |

1. 상속
타입스크립트에서는 일반적인 객체지향 패턴을 사용할 수 있습니다.
클래스 기반 프로그래밍의 가장 기본적인 패턴 중 하나는 상속을 이용하여 이미 존재하는 클래스를 확장해 새로운 클래스를 만들 수 있다는 것입니다.
예제를 봅시다.
class Animal { move(distanceInMeters: number = 0) { console.log(`Animal moved ${distanceInMeters}m.`); } } class Dog extends Animal { bark() { console.log('Woof! Woof!'); } } const dog = new Dog(); dog.bark(); dog.move(10); dog.bark();
타입이 추가된것을 제외하고 자바스크립트에서 보았던 클래스와 일치합니다. 이는 상속 기능을 보여주는 가장 기본적인 예제입니다.
여기서 조금 더 확장해보겠습니다.
class Animal { name: string; constructor(theName: string) { this.name = theName; } move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } } class Snake extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 5) { console.log('Slithering...'); super.move(distanceInMeters); } } class Horse extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 45) { console.log('Galloping...'); super.move(distanceInMeters); } } let sam = new Snake('Sammy the Python'); let tom: Animal = new Horse('Tommy the Palomino'); sam.move(); tom.move(34); // Slithering... // Sammy the Python moved 5m. // Galloping... // Tommy the Palomino moved 34m.
상속을 할 때 알아둬야할 것이 있습니다.
tom의 타입은 Animal 입니다. Horse는 Animal을 상속하였기 때문에 tom은 Horse값을 가지지만 Animal타입으로 선언이가능합니다.
하지만 아래 예제처름 만약 Horse에 추가되는 메서드가있다면 어떻게 될까요 ?
class Animal { name: string; constructor(theName: string) { this.name = theName; } move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } } class Horse extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 45) { console.log('Galloping...'); super.move(distanceInMeters); } speak( content: string) { console.log({content}) } } let tom: Animal = new Horse('Tommy the Palomino'); tom.move(34); tom.speak("hi")

위와 같이 에러가 발생합니다. 따라서 상속후에 추가적으로 메서드를 넣고자 한다면 이런식으로 타입을 정하면 안됩니다. 오히려 타입을 정하지 않으면 타입스크립트가 알아서 추론을 해줍니다.
위와 같이 자식 클래스에 부모 클래스 타입을 할당한다면 추가적인 메서드나 인자는 불가능하고 property 추가는 가능하다.
class Horse extends Animal { save: number; constructor(name: string) { super(name); this.save = 0; } move(distanceInMeters = 45) { console.log('Galloping...'); this.save = distanceInMeters; super.move(distanceInMeters); } } let tom: Animal = new Horse('Tommy the Palomino'); tom.move(34);
2. Public, private, protected Member
타입스크립트에서는 특정 메서드나 properties가 클래스 외부의 코드에 표시되는 여부를 제어할 수 있습니다.
그것들을 제어하는 Member가 바로 Public, private, protected 위 3가지입니다.
class test { public first : number; private second : number; protected third : number; constructor() { this.first = 1; this.second = 2 this.third = 3 } }
타입스크립트는 위와 같이 public, private, protected 3가지 Member가 있습니다.
각각이 무엇인지 배우기 전에 알아둬야할 것이 있습니다.
이 3가지는 타입스크립트에서만 유효합니다. 자바스크립트에서는 아예 표시 되지않습니다.

1) public
타입스크립트에서는 기본적으로 메서드나 property를 생성하면 public이 됩니다. 즉, 굳이 public을 해주지 않아도 기본값이 public 자동으로 된다는 소리입니다.
따라서 명확히 public이라는 것을 강조하고 싶을 때는 사용하셔도 됩니다.
class Animal { public name: string; public constructor(theName: string) { this.name = theName; } public move(distanceInMeters: number) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
2) protected
protected는 자신이 선언된 클래스의 하위 클래스에서만 엑세스 할 수 있습니다.
class Greeter { public greet() { console.log("Hello, " + this.getName()); } protected getName() { return "hi"; } } class SpecialGreeter extends Greeter { public howdy() { // OK to access protected member here console.log("Howdy, " + this.getName()); } } const g = new SpecialGreeter(); g.greet(); // OK g.getName(); // ~~~~~~~~ // Property 'getName' is protected and only accessible within class 'Greeter' and its subclasses.
3) private
private는 protected와 비슷하지만 하위 클래스에서도 멤버에 대한 액세스를 허용하지 않습니다.
class Base { private x = 0; } const b = new Base(); // Can't access from outside the class console.log(b.x); // Property 'x' is private and only accessible within class 'Base'. class Derived extends Base { showX() { // Can't access in subclasses console.log(this.x); // Property 'x' is private and only accessible within class 'Base'. } }
4) 주의할 점
private , protected 유형 검사 중에 대괄호 표기법을 사용하여 액세스 할 수도 있습니다.
이는 유닛 테스트와 같은 것들에 대해 private 선언 필드를 잠재적으로 더 쉽게 액세스할 수 있게 만들지만, 결국 private , protected 는 엄격하게 제한하지 않고 soft 하게 제한한다는 뜻입니다.
class MySafe { protected secretKey = 12345; private secretKey2 = 6789; } const s = new MySafe(); // Not allowed during type checking console.log(s.secretKey); // Property 'secretKey' is protected and only accessible within class 'MySafe' and its subclasses. console.log(s.secretKey2); // Property 'secretKey2' is private and only accessible within class 'MySafe'. // OK console.log(s['secretKey']); console.log(s['secretKey2']);
따라서 엄격하게 property를 제어하고 싶다면 자바스크립트에도 있고 타입스크립트에서도 지원하는 "#"(ECMAScript 비공개 필드)을 사용하면 좋습니다.
class MySafe { #secretKey = 12345; #secretKey2 = 6789; getKey() { return [this.#secretKey, this.#secretKey2]; } } const s = new MySafe(); console.log(s.getKey()); // [12345, 6789] // Not allowed during type checking console.log(s.secretKey); // Property 'secretKey' is protected and only accessible within class 'MySafe' and its subclasses. console.log(s.secretKey2); // Property 'secretKey2' is private and only accessible within class 'MySafe'. console.log(s['#secretKey']); // Property '#secretKey' does not exist on type 'MySafe' console.log(s['#secretKey2']); // Property '#secretKey2' does not exist on type 'MySafe' console.log(s['secretKey']); // Property '#secretKey' does not exist on type 'MySafe' console.log(s['secretKey2']); // Property '#secretKey2' does not exist on type 'MySafe'
❗️ 악의적인 사용자로부터 클래스의 값을 보호해야 하는 경우 클로저, WeakMaps 또는 개인 필드와 같은 갈력한 런타임 프라이버시를 제공하는 매커니즘을 사용해야 합니다. 런타임 동안 private, protected는 property or 메서드를 완벽하게 보호하지 못합니다.
끝으로 간단하게 복습해보겠습니다.

3. Readonly 지정자
readonly 키워드를 사용하여 property를 읽기 전용으로 만들 수 있습니다. 읽기 전용 프로퍼티들은 선언 또는 생성자에서 초기화해야 합니다.
class Octopus { readonly name: string; readonly numberOfLegs: number = 8; constructor (theName: string) { this.name = theName; } } let dad = new Octopus("Man with the 8 strong legs"); dad.name = "Man with the 3-piece suit"; // 오류! name은 읽기전용 입니다.
4. 추상 클래스 (Abstract Classes)
추상 클래스는 다른 클래스들이 파생될 수 있는 기초 클래스입니다.
추상 클래스는 직접 인스턴스화할 수 없습니다.
추상 클래스는 인터페이스와 달리 멤버에 대한 구현 세부 정보를 포함할 수 있습니다.
abstract 키워드는 추상 클래스뿐만 아니라 추상 클래스 내에서 추상 메서드를 정의하는데 사용됩니다.
abstract class Animal { abstract makeSound(): void; move(): void { console.log("roaming the earth..."); } }
추상 클래스 내에서 추상으로 표시된 메서드는 구현을 포함하지 않으며 반드시 파생된 클래스에서 구현되어야 합니다.
추상 메서드는 인터페이스 메서드와 비슷한 문법을 공유합니다. 둘 다 메서드 본문을 포함하지 않고 메서드를 정의합니다.
그러나 추상 메서드는 반드시 abstract 키워드를 포함해야하며, 선택적으로 접근 지정자를 포함할 수 있습니다.
abstract class Department { constructor(public name: string) { } printName(): void { console.log("Department name: " + this.name); } abstract printMeeting(): void; // 반드시 파생된 클래스에서 구현되어야 합니다. } class AccountingDepartment extends Department { constructor() { super("Accounting and Auditing"); // 파생된 클래스의 생성자는 반드시 super()를 호출해야 합니다. } printMeeting(): void { console.log("The Accounting Department meets each Monday at 10am."); } generateReports(): void { console.log("Generating accounting reports..."); } } let department: Department; // 추상 타입의 레퍼런스를 생성합니다 department = new Department(); // 오류: 추상 클래스는 인스턴스화 할 수 없습니다 department = new AccountingDepartment(); // 추상이 아닌 하위 클래스를 생성하고 할당합니다 department.printName(); department.printMeeting(); department.generateReports(); // 오류: 선언된 추상 타입에 메서드가 존재하지 않습니다
5. 인터페이스 처럼 사용하기
클래스를 인터페이스 처럼 사용할 수 있습니다.
클래스 선언은 클래스의 인스턴스를 나타내는 타입과 생성자 함수라는 두 가지를 생성합니다.
클래스는 타입을 생성하기 때문에 인터페이스를 사용할 수 있는 동일한 위치에서 사용할 수 있습니다.
class Point { x: number; y: number; } interface Point3d extends Point { z: number; } let point3d: Point3d = {x: 1, y: 2, z: 3};
source
'Typescript > 개념' 카테고리의 다른 글
[Typescript] tsconfig.json 옵션 (0) | 2023.08.22 |
---|---|
[TypeScript] generics (0) | 2023.02.15 |
[Typescript] void (0) | 2023.02.14 |
[Typescript] 3. Polymorphism / generics (0) | 2023.01.19 |
[Typescript] declare (0) | 2022.12.28 |