TypeScript 모르고 지나쳤을 기초 개념에 관하여

🪐 C:on·2022년 1월 2일
0

타입스크립트

목록 보기
2/3


🔎 리터럴 타입

리터럴 타입은 구체적인 타입을 얘기한다.

예를 들어 타입을 hello라는 타입을 새로 정의하면 이것을 대상타입으로 갖는 변수에는 꼭 hello라는 문자열만 할당될 수 있다.


리터럴타입 타입추론

const helloWorld = "Hello World";

let hiWorld = "Hi World";

const는 변하지 않으므로 helloWorld의 타입은 "Hello World"가 된다.
반면 let은 변할 수 있으므로 hiWorld의 타입은 string이 된다.


유니온 타입

유니언 타입은 여러 타입 중 하나가 될 수 있는 값을 의미한다.

세로 막대 (|)로 각 타입을 구분하여, number | string | boolean은 값의 타입이 number, string 혹은 boolean이 될 수 있음을 의미한다.

interface Bird {
  fly(): void;
  layEggs(): void;
}

interface Fish {
  swim(): void;
  layEggs(): void;
}

declare function getSmallPet(): Fish | Bird;

let pet = getSmallPet();
pet.layEggs();

pet.swim();

두 타입이 동시에 가진 멤버인 layEggs는 확실히 가진 것이므로 호출이 가능하다.
하지만 swim은 확신할 수 없는 멤버이므로 호출할 수 없다.


교차타입

교차 타입은 여러 타입을 하나로 결합한다.

기존 타입을 합쳐 필요한 기능을 모두 가진 단일 타입을 얻을 수 있다.

결합을 하기 위해선 인터페이스로 규격해야한다.
type은 결합이 불가능하다.




🔎 클래스

기존 JavaScript는 재사용할 수 있는 컴포넌트를 만들기 위해 함수와 프로토타입-기반 상속을 사용했지만, 객체 지향 접근 방식에 익숙한 프로그래머의 입장에서는 클래스가 함수를 상속받고 이런 클래스에서 객체가 만들어지는 것에 다소 어색함을 느꼈다.

ECMAScript 2015를 시작으로 JavaScript 프로그래머들은 이런 객체-지향적 클래스-기반의 접근 방식을 사용해서 애플리케이션을 만들 수 있게 되었다.


상속

파생된 클래스의 생성자 함수는 기초 클래스의 생성자를 실행하려면 super()를 호출해야 한다.
또는 생성자 내의 this에 있는 프로퍼티에 접근하려면 그 전에 super()를 호출해야 한다.

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);
    }
}

상속된 메서드와 동일한 메서드가 정의되면 새로 정의된 메서드를 따른다.

위에서는 Snake 인스턴스는 move를 오버라이드 해서 각각 클래스의 특성에 맞게 기능을 가진 move를 재생산했다.


private

멤버에 접근하지 못하도록 하려면 멤버를 private으로 표시하는 방법을 사용할 수 있다.

타입스크립트는 privateprotected 멤버가 있는 타입들을 비교할 때는 타입을 다르게 처리한다.
호환된다고 판단되는 두 개의 타입 중 한 쪽에서 private 멤버를 가지고 있다면, 다른 한 쪽도 무조건 동일한 선언에 private 멤버를 가지고 있어야 하며 protected 멤버도 똑같이 적용된다.

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

class Rhino extends Animal {
    constructor() { super("Rhino"); }
}

class Employee {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");

animal = rhino;
animal = employee; // 오류: 'Animal'과 'Employee'은 호환될 수 없음.

RhinoAnimal을 상속하여 super()를 호출했기 때문에 동일한 멤버를 가지고 잇어 호환이 가능하다.

하지만 Employee는 전혀 다른곳에서 선언을 한 멤버이기 때문에 호환이 불가능하고 오류가 발생한다.


읽기전용 지정자

readonly 키워드를 작성해서 프로퍼티를 오직 읽을 수만 있도록 지정할 수 있다.


추상클래스

다른 클래스들이 파생될 수 있는 기초클래스로 그 자체만으로는 인스턴스화할 수 없다.

인터페이스와 차이점은 멤버에 대한 구현 세부 정보를 포함할 수 있다는 것이다.

abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log("roaming the earth...");
    }

추상 클래스 내의 메서드를 abstract를 사용하여 추상메서드로 정의할 수 있다.

추상메서드는 구현 정보를 포함하지 않고 파생된 클래스에서 구현하게 된다.






















0개의 댓글