class
보통 자바스크립트에서는 Constructor 함수를 만들고 그 안에
this.firstName = firstName 혹은 this.lastName = lastName 같은 코드를 넣어줄 것이다.
하지만 타입스크립트는 이렇게 하지 않아도 된다.
파라미터들을 써주기만 하면 타입스크립트가 알아서 Constructor함수를 만들어준다.
// js
"use strict";
class Player {
constructor(firstName, lastName, nickname) {
this.firstName = firstName;
this.lastName = lastName;
this.nickname = nickname;
}
}
const coco = new Player("coco", "chanel", "코코")
// ts
class Player {
constructor(
private firstName:string,
private lastName:string,
public nickname:string
) {}
}
const coco = new Player("coco", "chanel", "코코")
추상 클래스
타입스크립트와 객체지향 프로그램이 가지고 있는 엄청 훌륭한 것은 추상클래스이다.
추상클래스는 다른 클래스가 상속받을 수 있는 클래스이다.
하지만 이 클래스는 직접 새로운 인스턴스를 만들 수는 없다.
abstract class User {
constructor(
private firstName:string,
private lastName:string,
public nickname:string
) {}
}
class Player extends User {
}
const coco = new Player("coco", "chanel", "코코")
// ❌ 여기서 아래처럼 바로 추상클래스의 인스턴스를 생성할 수 없다.
const kaka = new User("kaka", "o", "카카오")
쉽게이야기해서 추상 클래스는 상속 받을 수만 있고, 인스턴스를 직접적으로 만들 수는 없다.
추상 메서드
추상 클래스 안에서는 추상 메서드를 만들 수 있다.
하지만 메서드를 구현하면 안되고 대신에 메서드의 call signature 만 적어둬야한다.
추상 메서드는 추상클래스를 상속받는 모든 것들이 구현을 해야하는 메서드를 의미한다.
구현은 어떻게 되어도 상관없지만 구현을 자체를 하기를 원한다.
abstract class User {
constructor(
private firstName:string,
private lastName:string,
private nickname:string
) {}
abstract getNickName():void
}
class Player extends User {
}
이 코드를 보면 getNickName이라는 추상 메서드는 call signature만을 가지고 있다. (여기에는 argument를 추가해줄 수도 있다)
이렇게 하면 밑에 Player class에 빨간 밑줄이 생기면서 getNickName을 구현해야한다고 알려준다.
protected
그래서 이제 만들려고 하면 여기서 문제가 또 발생한다.
User에서 private으로 nickname을 설정하여 User 클래스외에는 접근이 불가능 하다.
이럴때 필요한게 바로 protected이다.
abstract class User {
constructor(
protected firstName:string,
protected lastName:string,
protected nickname:string
) {}
abstract getNickName():void
}
class Player extends User {
getNickName() {
console.log(this.nickname)
}
}
const coco = new Player("coco", "chanel", "코코")
이런식으로 protected를 해주면 내부에서는 User클래스와 User클래스로부터 상속받은 클래스 내부에서만 접근이 가능하고 클래스 외부에서는 접근이 불가능해진다.
4.2 interfaces
type Nickname = string;
type Player = {
nickname: Nickname,
healthBar: number
};
const kim: Player = {
nickname: "kim",
healthBar: 10,
};
이런식으로 type을 지정해줄 수 있다.
type Team = "red" | "blue" | "yellow"
type Health = 1 | 5 | 10
type Player = {
nickname: string,
health: number,
team:Team,
};
const nico : Player = {
nickname:"nico",
team: "yellow",
health : 10
}
이렇게 특정값을 갖게 설정해줄 수도 있다.
또 다르게 타입을 설정해줄 수 있다.
바로 " interface "이다.
interface
type Team = "read" | "blue" | "yellow";
type Health = 1 | 5 | 10;
interface Player {
nickname: string;
team: Team;
health: number;
}
const kim: Player = {
nickname: "kim",
team: "yellow",
health: 10,
};
단 이렇게는 동작하지 않는다.
interface Hello = string // x
interface는 오로지 오브젝트의 모양을 타입스크립트에게 설명해 주기 위해서만 사용되는 키워드이다.
아래처럼도 사용가능하다
interface User {
name:string
}
interface Player extends User {
}
const nico : Player = {
name: "nicoo"
}
만약 이걸 type으로 나타낸다면
type User {
name:string
}
type Player = User & {
}
const nico : Player = {
name: "nicoo"
}
또한 각각 따로 만들어도 타입스크립트가 알아서 합쳐준다. (type으로는 아래와 같이 불가함)
interface User{
name:string
}
interface User {
lastName : string
}
interface User {
health: number
}
const nico : User ={
name: "nico",
lastName:"no",
health:10
}
interface와 type은 같은 목적으로 사용할 수 있는데, 둘다 타입스크립트에게 오브젝트의 모양을 알려줄 수 있다.
같은 목적을 이루기 위해 타입과 인터페이스를 쓸 수 있다.
interface의 장점
abstract class
추상 클래스는 이걸 상속받는 다른 클래스가 가질 property와 메소드를 지정하도록 해준다.
추상 클래스는 단지 다른 클래스가 따라야할 청사진만 제시할 뿐이다.
만약 User 클래스를 상속한다면 반드시 sayHi랑 fullName을 구현해야한다. 메소드를 구현해야한다.(아래처럼)
(주의 new User() 와 같은 인스턴스를 만들 수 없다.)
하지만 이렇게 만들면 js가 추상 클래스까지 인식해서 파일 용량이 늘어난다.
여기서 바로 추상클래스의 기능을 그대로 가져오면서 js가 추적하지 못해서 play클래스만 인식하도록 하는 방법이 있다.
바로 interface를 사용하는 것이다.
이런식으로 하면 오른쪽에 js로 변환된 것을 본다면 추상 클래스때 user 클래스가 보인 것과는 다르게 play클래스만 보이게 된다.
이렇게 함으로서 파일 용량을 줄일 수 있다. (즉 interface로 interface는 js로 컴파일되지 않는다.
(단, Player 클래스에서 protected or private는 사용할 수 없다 )
아래처럼 함수의 매개변수에도 활용할 수 있다.
복습
type과 interface 비교
type PlayerA = {
name:string
}
//상속
type PlayerAA = PlayerA & {
lastName:string
}
const playerA: PlayerA ={
name: "nico",
lastName:"xxx"
}
////////
interface PlayerB {
name:string
}
//상속
type PlayerBB extends playerB{
lastName:string
}
//or
interface PlayerBB {
health:number
}
const playerB: playerB ={
name: "nico",
lastName:"xxx",
health:0
}
interface는 위와 같이 확장이 자유자재로 가능하고 type은 불가능하다 .
'Typescript > 개념' 카테고리의 다른 글
[Typescript] 3. Polymorphism / generics (0) | 2023.01.19 |
---|---|
[Typescript] declare (0) | 2022.12.28 |
[Typescript] call signatures // overloading (0) | 2022.09.22 |
[Typescript] Type part 3 ( unknown / void / never ) (1) | 2022.09.21 |
[Typescript] Type part 2 ( readonly / Tuple / any ) (1) | 2022.09.21 |