본문 바로가기

개발공부/TypeScript

TypeScript 타입별칭(Type Alias)과 인덱스 시그니쳐(Index Signature)

타입별칭(Type Alias)

타입 별칭을 이용하면 변수를 선언하듯 타입을 별도로 정의할 수 있다.

// 타입별칭
type User = {
    id: number;
    name: string;
    nickname: string;
    birth: string;
    bio: string;
    location: string;
};

let user: User = {
    id: 1,
    name: "김감자",
    nickname: "kim potato",
    birth: "2001.01.01",
    bio: "하이요",
    location: "부산시"
}

type 타입이름 = 타입 형태로 타입을 정의한다.
위 코드는 타입 이름으로는 User, 타입으로는 여러개의 프로퍼티가 있는 객체 타입이 정의되어 있다.

참고로 동일한 스코프에서 동일한 이름의 타입별칭을 선언하는 것은 불가능하다.(마치 변수 선언과 비슷하다.)

하지만 위 이미지와 같이 스코프가 다르다면 중복된 이름으로 여러개의 별칭을 선언해도 상관없다.

위 이미지와 같이 타입관련 문법은 컴파일과 함께 모두 사라진다.
(컴파일을 하기 위해서는 터미널창에 tsc명령어를 입력해주면 되고, 그 결과로 생성된 자바스크립트 파일을 통해 컴파일 결과를 확인할 수 있다.)

인덱스 시그니처(Index Signature)

인덱스 시그니처는 객체 타입을 유연하게 정의할 수 있도록 돕는 특수한 문법이다.

type CountryCodes = {
    Korea: string;
    UnitedState: string;
    UnitedKingdom: string;
};

let countryCodes: CountryCodes = {
    Korea: "ko",
    UnitedState: "us",
    UnitedKingdom: "uk",
};

위와 같은 예제 코드에서는 국가를 3개밖에 표현해주지 않았지만 전 세계의 국가코드를 표현하자고 하면 그만큼 CountryCodes에도 프로퍼티를 정의해줘야 하기 때문에 상당히 불편할것같다.

인덱스 시그니처 사용하기

바로 이런 상황에서 인덱스 시그니처를 이용하면 간단하게 타입을 정의할 수 있다.

type CountryCodes = {
    [key: string]: string;
};

let countryCodes: CountryCodes = {
    Korea: "ko",
    UnitedState: "us",
    UnitedKingdom: "uk",
    // ...전세계 국가
    Brazil: "bz",
};

여기서 [key: string]: string은 인덱스 시그니처 문법으로 이 객체 타입에는 key: string타입이고 value가 string타입인 모든 프로퍼티를 포함한다. 라는 의미이다.

따라서 Korea: "ko" 나 Brazil: "bz"처럼 key와 value가 모두 string 타입인 이런 프로퍼티들이 타입에 자동으로 모두 포함된다.
즉, 인덱스 시그니처를 이용하면 굳이 일일이 타입들을 직접 명시할 필요가 없어진다.

type CountryNumberCodes = {
    [key:string]: number;
}

만약 국가코드를 숫자로 보관하는 객체가 필요할때는 위와 같이 타입을 정의해주면 된다.
이때 반드시 포함해야하는 프로퍼티가 있을경우 직접 명시해도 된다.

인덱스 시그니처와 함께 추가적인 프로퍼티 표시하기

type CountryNumberCodes = {
    [key:string]: number;
    Korea: number;
}

주의사항 첫번째

여기서 한가지 주의해야할 점은 인덱스 시그니처를 사용하면서 동시에 추가적인 프로퍼티를 더 정의할 때에는
인덱스 시그니처의 value타입과 직접 추가한 프로퍼티의 value 타입이 호환되거나 일치해야 한다.
(위 코드에서는 [key: string]: number;'number'Korea: number;'number'가 일치하고 있다.)

만일 위 이미지처럼 일치하지 않을 경우 에러메세지가 발생하는데 에러메세지가 발생하는 이유는
인덱스 시그니처를 사용하는 어떤 객체타입에서 추가적인 Korea: string과 같은 프로퍼티를 정의해놓으려면 반드시 [key: string]: number의 값인 'number'와 동일하거나 호환되는 값으로 Korea의 값을 지정해야 한다.

 

주의사항 두번째

추가로 인덱스 시그니처를 이용하여 객체의 타입을 정의할때 객체에 아무런 값이 없어도 에러메세지가 발생하지 않는다.
이유는 인덱스 시그니처가 [key: string]: number;만 위반하지 않는다면 모든 객체를 허용하기 때문이다.

하지만 위 이미지처럼 추가로 명확하게 명시해둔 프로퍼티에 대해서는 Korea: number 인 프로퍼티가 반드시 필요하기때문에 해당과 같은 에러메세지가 보여지는 것이다.

정리

타입별칭은 type 타입이름 = 타입형태로 타입을 정의한다.
하지만 동일한 스코프에서 동일한 이름의 타입별칭을 선언하는것은 불가능하다.
(스코프가 다르다면 중복된 이름으로 여러개의 별칭을 선언할 수 있다.)

인덱스 시그니처는 객체 타입을 유연하게 정의할 수 있도록 돕는 특수한 문법이다.
타입을 정의할때 인덱스 시그니처로 표현한 프로퍼티 + 별도로 포함해야 하는 프로퍼티 형식으로 작성도 가능하지만
이때에는 인덱스 시그니처의 value타입과 별도로 포함된 프로퍼티의 value 타입이 호환되거나 일치하도록 작성되어야 한다.

 

 

관련강의 - 한입크기로 잘라먹는 타입스크립트(인프런)