조아마시

쓸모 있는 상세페이지 만들기

웹개발/typescript

[타입스크립트] 객체 타입

joamashi 2024. 8. 30. 22:00

타입스크립트의 객체 타입은 자바스크립트 객체의 구조와 특성을 명확하게 정의하는 데 사용됩니다. 이를 통해 개발자는 코드의 안정성을 높이고 예측 가능한 결과를 얻을 수 있습니다.

객체 타입 기본 구조

interface Person {
  name: string;
  age: number;
  isStudent: boolean;
}
  • interface: 객체의 형태를 정의하는 키워드입니다.
  • Person: 인터페이스의 이름입니다.
  • name, age, isStudent: 객체의 속성(property)이며, 각각의 타입이 명시되어 있습니다.

다양한 예시

1. 복잡한 객체

interface Address {
  street: string;
  city: string;
  zipCode: string;
}

interface User {
  id: number;
  name: string;
  email: string;
  address: Address;
}
  • Address 인터페이스는 주소 정보를 나타내고, User 인터페이스는 사용자 정보를 나타냅니다.
  • User 인터페이스의 address 속성은 Address 인터페이스 타입을 가짐으로써 객체의 중첩을 표현합니다.

2. 옵셔널 속성

interface Config {
  port: number;
  host?: string; // ?를 사용하여 옵셔널 속성으로 지정
}
  • host 속성은 선택적인 속성으로, 값이 없어도 에러가 발생하지 않습니다.

3. 읽기 전용 속성

interface ReadonlyUser {
  readonly id: number; // readonly를 사용하여 읽기 전용으로 지정
  name: string;
}
  • id 속성은 값을 변경할 수 없는 읽기 전용 속성입니다.

4. 인덱스 시그니처

interface Dictionary {
  [key: string]: string;
}
  • Dictionary 인터페이스는 임의의 문자열 키를 가진 문자열 값을 갖는 객체를 나타냅니다.

5. 함수 타입 속성

interface User {
  name: string;
  greet: (message: string) => string;
}
  • greet 속성은 함수 타입을 가지며, 문자열을 입력받아 문자열을 반환하는 함수를 의미합니다.

객체 타입 활용

  • 함수 파라미터: 함수에 전달되는 객체의 형태를 명확히 지정합니다.
  • 함수 반환값: 함수가 반환하는 객체의 형태를 명확히 지정합니다.
  • 변수 타입: 변수에 할당되는 객체의 형태를 명확히 지정합니다.
  • TypeScript 인터페이스: 다른 인터페이스와의 관계를 정의하고 복잡한 데이터 구조를 모델링합니다.

왜 객체 타입을 사용해야 할까요?

  • 코드 가독성 향상: 객체의 구조를 명확하게 보여주어 코드 이해를 돕습니다.
  • 타입 안전성 확보: 잘못된 값이 할당되는 것을 방지하여 오류를 줄입니다.
  • IDE 활용도 증가: 코드 자동 완성, 타입 검사 등 IDE 기능을 활용하여 생산성을 높입니다.
  • 대규모 프로젝트 관리 용이: 복잡한 데이터 구조를 효과적으로 관리할 수 있습니다.

타입스크립트는 객체의 형태를 정의하는 데 다양한 방법을 제공합니다. 지금까지 interface를 중심으로 살펴보았지만, 이 외에도 타입 별칭을 이용하여 객체 타입을 선언할 수 있습니다.

1. 인터페이스 (interface)

  • 가장 일반적으로 사용되는 방법입니다.
  • 객체의 구조를 명확하게 정의하고, 다른 인터페이스와의 상속 관계를 설정할 수 있습니다.
interface Person {
  name: string;
  age: number;
}

2. 타입 별칭 (type alias)

  • 인터페이스와 유사하지만, 더 유연하게 타입을 정의할 수 있습니다.
  • 함수 타입, 유니온 타입, 인터섹션 타입 등 다양한 타입을 조합하여 새로운 타입을 만들 수 있습니다.
type Person = {
  name: string;
  age: number;
};

인터페이스와 타입 별칭의 차이점:

  • 상속: 인터페이스는 다른 인터페이스를 상속할 수 있지만, 타입 별칭은 불가능합니다.
  • 재선언: 인터페이스는 같은 이름으로 여러 번 선언할 수 없지만, 타입 별칭은 가능합니다. (단, 타입이 동일해야 합니다.)

3. 객체 리터럴 타입

  • 객체를 직접 정의하여 타입으로 사용하는 방법입니다.
  • 간단한 객체 타입을 정의할 때 유용합니다.
type Person = {
  name: string;
  age: number;
};

let person1: Person = { name: 'Alice', age: 30 }; // 정확한 타입
let person2: { name: string; age: number } = { name: 'Bob', age: 25 }; // 객체 리터럴 타입 직접 사용

4. 제네릭 (Generics)

  • 타입을 매개변수화하여 재사용 가능한 타입을 만들 수 있습니다.
  • 다양한 종류의 데이터를 다룰 때 유용합니다.
interface GenericObject<T> {
  data: T;
}

let obj1: GenericObject<string> = { data: 'hello' };
let obj2: GenericObject<number> = { data: 42 };

5. 인덱스 시그니처

  • 객체의 프로퍼티 이름이 동적으로 결정될 때 사용합니다.
  • 모든 프로퍼티가 동일한 타입을 가질 때 유용합니다.
interface StringDictionary {
  [key: string]: string;
}

어떤 방법을 선택해야 할까요?

  • 간단한 객체: 객체 리터럴 타입 또는 타입 별칭
  • 복잡한 객체: 인터페이스 (상속, 확장성)
  • 재사용 가능한 타입: 제네릭
  • 동적인 프로퍼티: 인덱스 시그니처

이미 다양한 방법으로 객체 타입을 선언하는 방법을 알아보았지만, 좀 더 심화된 내용과 실제 개발에서 자주 사용되는 패턴들을 살펴보겠습니다.

1. 유니온 타입 (Union Types)

  • 서로 다른 타입 중 하나의 값을 가질 수 있도록 허용합니다.
  • 여러 가지 형태의 데이터를 처리해야 할 때 유용합니다.
type User = {
  name: string;
  age: number;
};

type Admin = {
  name: string;
  role: 'admin';
};

type Person = User | Admin; // User 또는 Admin 타입을 가질 수 있음

2. 인터섹션 타입 (Intersection Types)

  • 여러 타입의 모든 속성을 가지는 타입을 생성합니다.
  • 두 가지 이상의 타입의 특징을 모두 가지는 객체를 만들 때 유용합니다.
type Colorful = {
  color: string;
};

type Circle = {
  radius: number;
};

type ColorfulCircle = Colorful & Circle; // color와 radius 속성을 모두 가짐

3. 맵드 타입 (Mapped Types)

  • 기존 타입의 프로퍼티를 변형하여 새로운 타입을 생성합니다.
  • 여러 프로퍼티를 가진 객체의 타입을 일괄적으로 수정할 때 유용합니다.
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

interface Todo {
  title: string;
  completed: boolean;
}

type ReadonlyTodo = Readonly<Todo>; // 모든 프로퍼티가 읽기 전용

4. 조건부 타입 (Conditional Types)

  • 특정 조건에 따라 다른 타입을 반환합니다.
  • 복잡한 타입 계산에 사용됩니다.
type IsString<T> = T extends string ? true : false;

5. 인덱스 서명 (Index Signatures)

  • 객체의 동적 프로퍼티를 허용합니다.
  • 특정 패턴을 따르는 프로퍼티를 정의할 수 있습니다.
interface StringArray {
  [index: number]: string; // 모든 인덱스는 문자열 타입
}
728x90