[TypeScript] 값 공간과 타입 공간

김지훈·2024년 4월 28일
0

TypeScript 스터디

목록 보기
3/10
post-thumbnail

1. TypeScript는 값 공간과 타입 공간을 가진다.

값과 타입은 타입스크립트에서 별도의 네임스페이스에 존재한다.

interface Dog {
    name: string;
    age: number;
}

const Dog = {name: 'panggu', age: 11};

위 코드에서 interface로 정의된 Dog는 타입으로 사용되었고, const로 정의된 Dog는 값으로 사용되었다.


2. 값과 타입은 구분해서 작성해야 한다.

다음은 구조 분해 할당을 사용하여 함수를 정의하려고 한 것이다.

type Person = {
    name: string;
    age: number;
}

function email({ person: Person, subject: string, body: string }) {
  // 실패
}

원래 의도는 매개변수에 들어올 수 있는 객체 타입을 제한하는 것이었겠지만, 실제로는 Personstring이 값 공간에 있는 것으로 해석한다.

위 코드를 의도와 같이 작성하려면 아래와 같이 작성할 수 있다.

function email({ person, subject, body }: 
                   { person: Person, subject: string, body: string }) {
}

또는 type이나 interface를 사용할 수 있다.

interface EmailParams {
    person: Person;
    subject: string;
    body: string;
}

function email({ person, subject, body }: EmailParams) {
}

3. class는 값 공간과 타입 공간을 동시에 가진다.

class Developer {
    name: string;
    domain: string;

    constructor(name: string, domain: string) {
        this.name = name;
        this.domain = domain;
    }
}

const me: Developer = new Developer('jihun', 'front-end');

위 코드에서 me: 뒤에 사용된 Developer는 타입으로, new 키워드 뒤에 사용된 Developer는 클래스의 생성자 함수인 값으로 동작한다.


4. enum은 값 공간과 타입 공간을 동시에 가진다.

열거형 키워드 enum은 자바스크립트에서는 지원하지 않는 타입스크립트의 문법이다. enum도 클래스처럼 타입 공간에서 타입을 제한하는 역할을 한다.

enum Status {
  Ready,
  Waiting,
}
enum Color {
  Red,
  Blue,
  Green,
}
let status = Status.Ready;
status = Color.Green; // 실패

아래 예시에서는 enum이 타입으로 사용되어, printDay() 함수의 key 인자에 넘겨줄 수 있는 값의 타입을 제한한다.

enum WeekDays {
    MON = 'Mon',
    TUES = 'Tues',
    WEDNES = 'Wednes',
    THURS = 'Thurs',
    FRI = 'Fri',
}

type WeekDayKeys = keyof typeof WeekDays;
function printDay(key: WeekDayKeys, message: string) {
    const day = WeekDays[key];
    if (day <= WeekDays.WEDNES) {
        console.log(`It's still ${day}day, ${message}`);
    }
}
printDay('TUES', 'wanna go home');

✏️ 타입스크립트의 keyof 연산자는 해당 객체의 속성 키를 나타내는 유니온 타입을 생성한다.
위 코드에서 keyof typeof WeekDays를 통해 실제로 반환되는 값은 "MON" | "TUES" | "WEDNES" | "THURS" | "FRI"이다.

아래 예시와 같이 enumclass처럼 값 공간에서 사용될 수 있다.

enum MyColors {
    BLUE = '#0000FF',
    YELLOW = '#FFFF00',
    MINT = '#2AC1BC',
}

function whatMintColor(palette: { MINT: string }) {
    return palette.MINT;
}

console.log(whatMintColor(MyColors));

5. 타입을 확인하는 방법

타입스크립트에서 typeof 연산자는 값에서 쓰일 때와 타입에서 쓰일 때의 역할이 다르다. typeof 연산자가 값에서 사용되면 자바스크립트 런타임의 typeof 연산자로 작동하며, 타입에 사용되는 경우 타입스크립트 타입을 반환한다.

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

const person: Person = { first: 'jihun', last: 'kim' };

function email(options: { person: Person; subject: string; body: string }) {}

const v1 = typeof person; // 값은 'object'
const v2 = typeof email; // 값은 'function'

type T1 = typeof person; // 타입은 Person
type T2 = typeof email; 
// 타입은 (options: { person: Person; subject: string; body: string }) => void

typeof 연산자를 클래스에 적용할 때는 주의해야 한다. 아래 예시를 통해 살펴보자.

class Developer {
    name: string;
    sleepingTime: number;

    constructor(name: string, sleepingTime: number) {
        this.name = name;
        this.sleepingTime = sleepingTime;
    }
}

const d = typeof Developer; // 값은 'function'
type T = typeof Developer; // 타입은 typeof Developer

const me: Developer = new Developer('jihun', 7);
type MeType = typeof me; // 타입은 Developer
  • const d = typeof Developer;: 자바스크립트에서 클래스는 함수로서 취급되며, 클래스의 생성자 함수를 가리킨다. 따라서 d에 할당된 값은 function이다.
  • type T = typeof Developer;: TDeveloper 클래스 자체의 타입이다. 즉, T는 클래스의 생성자 함수를 포함하는 타입으로, 이 타입을 사용하여 Developer 클래스의 새 인스턴스를 아래와 같이 생성할 수 있다.
	const newInstance: InstanceType<T> = new Developer('홍길동', 10);

✏️ InstanceType<T>는 타입스크립트에서 제공하는 유틸리티 타입 중 하나로, 생성자 함수 타입 T의 인스턴스 타입을 생성한다.
즉, T가 클래스의 타입일 때, InstanceType<T>를 사용하면 해당 클래스의 인스턴스 타입을 얻을 수 있다.

  • type MeType = typeof me;: MeTypeme 인스턴스의 타입, 즉 Developer 클래스의 인스턴스 타입이다. 여기서 typeof meDeveloper를 반환하는 것이 아니라, me 변수가 가리키는 객체의 타입, 즉 Developer 인스턴스의 타입을 의미한다.

6. 타입 단언

타입 단언(Type Assertion)은 개발자가 타입스크립트 컴파일러보다 더 정확한 정보를 가지고 있을 때 사용한다. 즉, 개발자가 특정 변수의 타입을 명시적으로 지정해 컴파일러에게 알려주는 방식이다. 타입 단언은 컴파일 단계에서만 사용되며, 런타임에는 영향을 미치지 않는다. 타입 단언에는 두 가지 문법이 있다.

1. as를 사용한 방법

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

2. angle-bracket(<>)을 사용한 방법

let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

0개의 댓글