typescript에서의 class
타입스크립트는 클래스 문법에 대한 추가적인 지원이 있다.
따라서, 클래스를 작성할 때 타입스크립트는 자바스크립트와는 다른 문법을 사용하므로 이에 대해서 글을 남기도록 하였다.
interface & type
interface Bus {
custommer: string[];
driver: string;
callBus: () => string;
getCustomer: () => string[];
onBoardBus: (custommer: string) => void;
}
위와 같은 interface는 타입스크립트에서 객체의 타입을 표현하기 위해서 사용할 수 있다.
다만, java와 같은 객체지향 언어와 마찬가지로 interface를 implements하여 말 그대로 클래스의 인터페이스로 사용할 수 있다.
class MyBus implements Bus {
custommer: string[] = [];
driver = "me";
constructor(name: string) {
this.driver = name;
}
callBus = () => {
console.log(this.driver);
return this.driver
};
getCustomer = () => this.custommer;
onBoardBus = (custommer: string) => {
this.custommer.push(custommer);
}
}
만약, 인터페이스에 명시되었지만 이를 이식한 클래스에서 실제 구현이 되지 않은 변수나 함수가 있다면 타입스크립트 오류가 발생한다.
const myBus = new MyBus("Driver");
myBus.callBus();
console.log(myBus.driver);
console.log(myBus.getCustomer());
myBus.onBoardBus("Park");
myBus.onBoardBus("Lee");
myBus.onBoardBus("One");
myBus.onBoardBus("Bob");
myBus.onBoardBus("Test");
myBus.onBoardBus("Kim");
console.log(myBus.getCustomer());
구현한 클래스가 잘 작동함을 확인할 수 있다.
또한, type 키워드역시 implements 될 수 있다.
type Cup = {
id: number;
clean: () => void;
};
class Bottle implements Cup {
id: number = 12;
clean = () => console.log("clean");
}
abstract
타입스크립트에서는 자바스크립트와 달리 추상 클래스를 생성하여 사용할 수 있다.
추상클래스는 내부에 구현이 직접 될 수도 있고, abstract로 구현을 생략하고 상속받을 클래스에서 실제 구현을 할 수도 있다.
abstract class BusTime {
abstract arrivalTime: () => number;
consoleHello() {
console.log("hello");
}
}
class Bus extends BusTime {
arrivalTime: () => number = () => {
return new Date().getMinutes();
}
}
const bus = new Bus();
bus.consoleHello(); // hello
위와 같이 생성한 추상 클래스를 상속받아 구체적인 구현을 하는 문법과 추상 클래스에서의 직접 구현을 모두 지원한다.
abstract class BusTime {
abstract arrivalTime: () => number;
}
class Bus extends BusTime {
arrivalTime: () => number = () => {
return new Date().getMinutes();
}
}
또 다른 예제로 위와 같이 추상 클래스 BusTime을 생성하고 이를 상속받아 실제 구현을 할 수 있다.
다만, 위의 코드는 자바스크립트로 변환되며 쓸모없는 코드를 생성한다.
"use strict";
class BusTime {
}
class Bus extends BusTime {
constructor() {
super(...arguments);
this.arrivalTime = () => {
return new Date().getMinutes();
};
}
}
위의 변환된 자바스크립트 코드를 보면, 추상 클래스 BusTime은 무의미한 클래스가 되어버린다.
그리고 Bus는 이 빈 클래스를 상속받는 식으로 타입스크립트는 변환된다.
Private
타입스크립트는 java와 같은 객체지향언어처럼 private, public, protected 접근 제한자를 지원해준다.
그리고 자바스크립트에서 #을 붙여 클래스 외부에서 접근이 불가능한 변수를 만들 수 있다.
class MyBus {
public driver = "Jamie";
#busId = "javascript private";
private driverId = "typescript private";
}
const myBus = new MyBus();
console.log(myBus.driver);
myBus.#busId;
// Property '#busId' is not accessible outside class 'MyBus' because it has a private identifier.(18013)
myBus.driverId;
// Property 'driverId' is private and only accessible within class 'MyBus'.(2341)
🥒 #은 자바스크립트 문법이기에 런타임에서 에러가 발생하고, 타입스크립트 문법인 private는 컴파일 단계에서 에러가 발생한다.
다만, 우회를 통해서 private 타입스크립트가 자바스크립트로 컴파일 되면, 그 뒤로는 제약사항이 사라지기에 더 강력한 접근 제한을 위해서는 #을 사용할 수 있다.
"use strict";
var _MyBus_busId;
class MyBus {
constructor() {
this.driver = "Jamie";
_MyBus_busId.set(this, "javascript private");
this.driverId = "typescript private";
}
}
_MyBus_busId = new WeakMap();
const myBus = new MyBus();
console.log(myBus.driver);
🫑 위 타입스크립트는 자바스크립트가 되면서 private 키워드가 사라진다.