본문 바로가기
Typescript

Typescript | 객체, 타입 별칭, 인덱스 시그니쳐

by 리잼 2024. 10. 24.
반응형

객체 타입을 정의하는 방법

  • 타입 스크립트에서는 2가지 방식으로 객체의 타입을 정의할 수 있다.

 

object로 정의

// user 의 타입을 객체를 의미하는 object 로 정의
let user: object = {
  id: 1,
  name: "이정환",
};
  • 이렇게 하면 한 가지 문제가 있다.

user.id 를 점 표기법으로 객체의 특정 프로퍼티에 접근하려고 하면 오류가 발생한다.

  • 이유는 타입스크립트의 object 타입은 단순 값이 객체임을 표현하는 것 외에는 아무런 정보도 제공하지 않는 타입이기 때문
  • 따라서 이 타입은 객체의 프로퍼티에 대한 정보를 전혀 가지고 있지 않다
  • 그렇기 때문에 이렇게 프로퍼티에 접근하려고 하면 오류가 발생
  • 이럴 땐 obejct 가 아닌 객체 리터럴 타입을 이용해야함.

객체 리터럴 타입

객체 리터럴은 다음과 같이 중괄호를 열고 객체가 갖는 프로퍼티를 직접 나열해 만드는 타입

let user: {
  id: number;
  name: string;
} = {
  id: 1,
  name: "이정환",
};

user.id;
  • 변수 user의 타입을 number 타입의 id 그리고 string 타입의 name 프로퍼티를 갖는 객체 타입으로 정의
  • 이렇듯 객체 리터럴과 비슷한 문법으로 객체 타입을 정의한 타입을 객체 리터럴 타입이라고 부른다.

 

선택적 프로퍼티(Optional Property)

  • JS 에서 객체를 다루다보면 특정 프로퍼티는 있어도 되고 없어도 되는 상황이 존재함
  • 예를 들어 다음과 같이 이름은 있지만 아직 id가 없는 유저가 존재할 수도 있음
let user: {
  id: number;
  name: string;
} = {
  id: 1,
  name: "이정환",
};

user = {
  name: "홍길동", // 오류 발생!
};

 

이럴 때 선택적 프로퍼티를 설정하려면 프로퍼티 이름뒤에 "?" 를 붙여주면 된다.

let user: {
  id?: number; // 선택적 프로퍼티가 된 id
  name: string;
} = {
  id: 1,
  name: "이정환",
};

user = {
  name: "홍길동",
};

 

읽기전용 프로퍼티 (Readonly Property)

특정 프로퍼티를 읽기 전용으로 만들고 싶다면 프로퍼티의 이름 앞에 readonly 키워드를 붙이면 됨.

let user: {
  id?: number;
  readonly name: string; // name은 이제 Readonly 프로퍼티가 되었음
} = {
  id: 1,
  name: "이정환",
};

user.name = "dskfd"; // 오류 발생
  • name 프로퍼티는 읽기 전용이기 때문에 수정할 수 없음

타입 별칭 (Type Alias)

  • 타입 별칭을 이용하면 다음과 같이 변수를 선언하듯 타입을 별도로 정의가 가능
// 타입 별칭
// type 타입이름 = { ... } 로 정의
type User = {
  id: number;
  name: string;
  nickname: string;
  birth: string;
  bio: string;
  location: string;
};
...

 

이렇게 만든 타입은 변수의 타입을 정의할 때 타입 주석과 함께 사용 가능

type User = {
  id: number;
  name: string;
  nickname: string;
  birth: string;
  bio: string;
  location: string;
};

let user: User = {
  id: 1,
  name: "이정환",
  nickname: "winterlood",
  birth: "1997.01.07",
  bio: "안녕하세요",
  location: "부천시",
};

let user2: User = {
  id: 2,
  name: "홍길동",
  nickname: "winterlood",
  birth: "1997.01.07",
  bio: "안녕하세요",
  location: "부천시",
};

 

하지만 동일한 스코프에 동일한 이름의 타입 별칭을 선언하는 것은 불가능함

type User = {
  id: number;
  name: string;
  nickname: string;
  birth: string;
  bio: string;
  location: string;
};

type User = {}

 

스코프가 다르면 중복된 이름으로 여러개의 별칭해도 상관 없음

type User = {
  id: number;
  name: string;
  nickname: string;
  birth: string;
  bio: string;
  location: string;
};

function test() {
  type User = string;
}

 


인덱스 시그니처 (Index Signature)

객체 타입을 유연하게 정의할 수 있도록 돕는 특수한 문법이다

  • 다양한 국가들의 영어 코드를 저장하는 객체가 하나 있다고 가정
type CountryCodes = {
  Korea: string;
  UnitedState: string;
  UnitedKingdom: string;
};

let countryCodes: CountryCodes = {
  Korea: "ko",
  UnitedState: "us",
  UnitedKingdom: "uk",
};
  • 이 때 countryCodes 에 100개의 국가 코드가 추가 되어야 한다면 타입 정의에도 각 프로퍼티를 모두 정의 해줘야 하기 때문에 불편
type CountryCodes = {
  Korea: string;
  UnitedState: string;
  UnitedKingdom: string;
  // (... 약 100개의 국가)
  Brazil : string
};

let countryCodes: CountryCodes = {
  Korea: "ko",
  UnitedState: "us",
  UnitedKingdom: "uk",
  // (... 약 100개의 국가)
  Brazil : 'bz'
};
  • 이럴때 인덱스 시그니처를 이용하면 간단하게 타입을 정의할 수 있다.
//[key: string]: string 은 인덱스 시그니처 문법으로 이 객체 타입에는
// key 가 string 이고, value 가 string 인 타입인 프로퍼티를 포함 한다는 의미
type CountryCodes = {
  [key: string]: string;
};

let countryCodes: CountryCodes = {
  Korea: "ko",
  UnitedState: "us",
  UnitedKingdom: "uk",
  // (... 약 100개의 국가)
  Brazil : 'bz'
};
  • 만약 국가 코드를 숫자로 보관하는 객체가 하나 더 필요하다면 다음과 같이 정의하면 된다.
type CountryNumberCodes = {
  [key: string]: number;
};
  • 반드시 포함해야하는 프로퍼티가 있다면 직접 명시도 가능하다.
type CountryNumberCodes = {
  [key: string]: number;
  Korea: number;
};
  • 주의할 점은 인덱스 시그니처를 사용하면서 동시에 추가적인 프로퍼티를 정의할 때
    인덱스 시그니처의 value 타입과 직접 추가한 프로퍼티 value 의 타입이 호환하거나 일치해야한다
  • 따라서 다음과 같이 서로 호환되지 않는 타입으로 설정하면 오류가 발생
type CountryNumberCodes = {
  [key: string]: number;
  Korea: string; // 오류!
};
반응형

'Typescript' 카테고리의 다른 글

Typescript | 타입 호환성, 대수타입  (2) 2024.10.29
Typescript | void, never  (0) 2024.10.25
Typescript | Enum, any, unknown  (0) 2024.10.25
Typescript | 배열과 튜플  (1) 2024.10.24
Typescript | 원시, 리터럴 타입  (0) 2024.10.24