본문 바로가기

IT

Effective Typescript - 8 - 타입 공간과 값 공간의 심벌 구분하기

타입스크립트의 심벌(symbol)은 타입 공간이나 값 공간 중 한 곳에 존재합니다.

심벌은 같더라도 속하는 공간에 따라 다른 것을 나타냅니다. 따라서 이와 관련된 혼란이 올 수 도 있습니다. 

아래 예제가 바로 그러한 상황입니다.

//타입 공간에 존재
interface Cylinder {
    radius: number;
    height: number;
}

// 값 공간에 존재
const Cylinder = (
    radious : number,
    height: number
) => ({radious: radious, height: height});

위와 같은 상황에 혼란에 빠지면 아래와 같은 상황에 직면할 수 있습니다.

//타입 공간에 존재
interface Cylinder {
    radius: number;
    height: number;
}

// 값 공간에 존재
const Cylinder = (
    radious : number,
    height: number
) => ({radious: radious, height: height});

function
calcVol(shape: unknown) {
    // 런타인에 동작하는 instanceof 연산은 값 공간의 Cylinder를 참조함
    if(shape instanceof Cylinder) {
        shape.radius // 오류임.
    }
}

리터럴을 사용할 때도 심볼이 타입 공간에 존재하게 되는지, 값 공간에 존재하게 되는지 확실히 알고 있어야 합니다.

type T1 = 'string literal'; // 타입으로 타입 심볼이 타입 공간에 존재
type T2 = 123; // 타입으로 타입 심볼이 타입 공간에 존재

const v1 = 'string literal'; // 심볼이 값 공간에 존재
const v2 = 123; // 심볼이 값 공간에 존재

타입스크립트 코드에서 타입과 값은 번갈아 나올 수 있습니다. 타입 선언 ':' 또는 단언문 'as' 다음에 나오는 심벌은 타입 인 반면, '=' 뒤에 나오는 것은 값입니다.

 

class와 enum은 상황에 따라 타입과 값 모두 가능한 예약어 입니다. 

아래 예제의 Cylinder 클래스는 타입으로 쓰였습니다.

class Cylinder {
    radius=1;
    height=1;
}

function calcVol(shape: unknown){
    if(shape instanceof Cylinder){
        shape; // 정상, 타입은 Cylinder;
        shape.radius; // 정상, 타입은 number
    }
}

클래스가 타입으로 쓰일 때는 형태(속성과 메서드)가 사용되는 반면, 값으로 쓰일 때는 '생성자'가 사용됩니다.

 

한편, 연산자 중에서도 타입에서 쓰일 때와 값에서 쓰일 때 다른 기능을 하는 것들이 있습니다. 그 예 중에 하나로 typeof를 들 수 있습니다.

type T1 = typeof p; // 타입이 Person
type T2 = typeof email; // 타입 Email

const v1 = typeof p; // 값이 "object"
const v2 = typeof email; // 값이 "function"

타입의 관점에서 typeof는 타입 스크립트 타입을 반환합니다.

값의 관점에서 typeof는 자바스크립트 typeof 연산자가 됩니다.

class Cylinder {
    radius=1;
    height=1;
}

const v = typeof Cylinder; // 값이 "function";
type T = typeof Cylinder // 타입이 Cylinder;

 

아래는 타입의 속성 접근자에 대한 예제입니다. 자세한 내용은 아이템 14에서 다룹니다.

interface Person{
    first: string;
    last: string;
}

type PersonEl = Person['first' | 'last'] // 타입이 string;
type Tuple = [string, number, Date];
type TupleEl = Tuple[number]; // 타입은 string | number | Date

 

그리고 값 공간과 타입 공간 사이에서 다른 의미를 가지는 코드 패턴들이 있습니다.

* 값으로 쓰이는 this는 자바스크립트의 this 키워드 입니다.(아이템 49).

* 타입으로 쓰이는 this는 '다형성 this' 라고 불리는 this 타입스크립트 타입입니다. 서브클래스의 메서드 체인을 구현할 때 유용합니다.

* 값에서 &와 | 는 AND와 OR 연산입니다.

* 타입에서 &와 | 는 인터섹션(교집합)과 유니온(합집합) 입니다.

* const는 새 변수를 선언하지만, as const는 리터럴 또는 리터럴 표현식의 추론된 타입을 바꿉니다.

* extends는 서브클래스 또는 서브타입 또는 제너릭 타입에서의 한정자를 정의할 수 있습니다.

* in은 루프(for [key in object]) 또는 매핑된(mapped) 타입에 등장합니다.