TypeScript Study Note

Ginie·2021년 1월 27일
0

TypeScript

목록 보기
11/11
post-thumbnail

고급타입

교차 타입

  • 기존 타입을 합쳐 필요한 모든 기능을 가진 하나의 타입을 얻을 수 있다.
  • 믹스인을 만들 수 있다.

교차 타입을 더 알아보려면 여기를 클릭하세요

유니언 타입

  • 가끔 숫자나, 문자열을 매개변수로 기대하는 라이브러리를 사용할 때가 있다.
function padLeft(value: string, padding: any) {
  // padding이 any 타입으로 되어 있어 숫자나 문자열 둘 다 아닌 인수로 호출할 수 있다.
  // 문자열을 받고 왼쪽에 "padding"을 추가합니다.
    if (typeof padding === 'number') {
      // 만약 'padding'이 숫자라면, 그 숫자만큼의 공백이 왼쪽에 더해질 것입니다.
        return Array(padding + 1).join(' ') + value;
    }
    if (typeof padding === 'string') {
      // 만약 'padding'이 문자열이라면, 'padding'은 왼쪽에 더해질 것입니다.
        return padding + value;
    }
    throw new Error(`Expected string or number, got '${padding}'.`);
}
console.log(padLeft('Hello world', 4)); // "    Hello world"

// any 대신에 유니언 타입을 매개변수를 사용 할 수 있다.
function padLeft(value: string, padding: string | number) {
  //...
}

let indentedString = padLeft('Hello world', true); // 컴파일 중에 오류 
  • 유니언 타입은 값이 여러 타입 중 하나라고 말한다. | 로 타입을 구분한다.
  • 유니언 타입을 값으로 가지면 유니언에 있는 모든 타입에 공통인 멤버에만 접근이 가능하다.
interface Bird {
    fly();
    layEggs();
}

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

function getSmallPet(): Fish | Bird {
    //...
}

let pet = getSmallPet();
pet.layEggs(); // 성공
pet.swim(); // 오류 
pet.fly(); // 오류
  • 값의 타입이 겹쳐질 수 있는 상황을 모델링하는데 유니언 타입이 유용하다.
  • Fish가 있는지 구체적으로 알고 싶을 때
let pet = getSmallPet();

if (pet.swim) {
    pet.swim();
} else if (pet.fly) {
    pet.fly();
} // 둘 다 오류, 공통된 타입을 갖고 있지 않으면 각 프로퍼티에 접근하는 것은 오류가 난다.

// 이 코드를 동작하게 하려면 **타입 단언 as**를 사용하자.
if ((pet as Fish).swim) {
    (pet as Fish).swim();
} else if ((pet as Bird).fly) {
    (pet as Bird).fly();
}

사용자 정의 타입 가드

  • 타입 가드는 스코프 안에서의 타입을 보장하는 런타임 검사를 수행한다.
  • 타입 가드를 정의하려면 리턴 타입이 타입 서술어인 함수를 정의하자.
function isFish(pet: Fish | Bird): pet is Fish {
    return (pet as Fish).swim !== undefined;
}
  • parameterName is Type는 타입 서술어 이다. 예제에서는 pet is Fish
  • parameterName는 반드시 현재 함수 시그니처의 매개변수 이름이여야 한다.
// 모든 프로퍼티에 접근이 가능하다.
if (isFish(pet)) {
    pet.swim();
} // TS는 pet이 Fish 라는 것을 알고 있다.
else {
    pet.fly();
} // Fish가 없다는 것도 알고 있다. 그래서 Bird를 반드시 가지고 있어야 한다.

in연산자 사용하기

  • in은 타입을 좁히는데 사용한다.
  • n(문자열 타입 또는 문자열) in x(유니언 타입)
    • true라면 선택적 혹은 필수적 프로퍼티n을 가지는 타입으로 좁히고 false라면 선택적 혹은 누락된 프로퍼티 n을 가지는 타입으로 좁힌다.

typeof 타입 가드

function isNumber(x: any): x is number {
    return typeof x === 'number';
}

function isString(x: any): x is string {
    return typeof x === 'string';
}

function padLeft(value: string, padding: string | number) {
    if (isNumber(padding)) {
        return Array(padding + 1).join(' ') + value;
    }
    if (isString(padding)) {
        return padding + value;
    }
    throw new Error(`Expected string or number, got '${padding}'.`);
}

// 이걸 원시값인지 확인하는 함수를 줄일 수 있다. typeof를 통해서!

function padLeft(value: string, padding: string | number) {
    if (typeof padding === "number") {
        return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
        return padding + value;
    }
    throw new Error(`Expected string or number, got '${padding}'.`);
}

instanceof 타입 가드

  • 생성자 함수를 이용해 타입을 좁힌다.
  • instanceof 오른쪽은 생성자 함수여야 한다.
    • TS는 밑의 순서대로 좁혀간다.
    1. 함수의 prototype 프로퍼티 타입이 any가 아닌 경우
    2. 타입의 생성자 시그니처에서 반환된 유니언 타입일 경우
interface Padder {
    getPaddingString(): string
}

class SpaceRepeatingPadder implements Padder {
    constructor(private numSpaces: number) { }
    getPaddingString() {
        return Array(this.numSpaces + 1).join(' ');
    }
}

class StringPadder implements Padder {
    constructor(private value: string) { }
    getPaddingString() {
        return this.value;
    }
}

function getRandomPadder() {
    return Math.random() < 0.5 ?
        new SpaceRepeatingPadder(4) :
        new StringPadder(' ');
}
// 타입은 'SpaceRepeatingPadder | StringPadder' 이다.
let padder: Padder = getRandomPadder();
if (padder instanceof SpaceRepeatingPadder) {
    padder; // 타입은 'SpaceRepeatingPadder'으로 좁혀진다.
}

if (padder instanceof StringPadder) {
    padder; // 타입은 'StringPadder'으로 좁혀진다.
}
profile
느리지만 꾸준한 프론트엔드 주니어 개발자 🐢

0개의 댓글