Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

developer_kcm

타입스크립트 문법 (Interface, Alias) 본문

Typescript

타입스크립트 문법 (Interface, Alias)

fullkeem 2024. 6. 1. 23:25

인터페이스(Interface)

- 객체의 구조를 정의하는데 사용한다.

 

선택적 속성 - ?

읽기전용 속성 - readonly

  interface User {
    name: string
    age: number
    isValid: boolean
  }

  const eddie: User = {
    name: 'Eddie',
    age: 25,
    isValid: true
  }

1.함수 타입 - 호출 시그니처(Call Signature)

- 호출 시그니처인 소괄호"()"를 통해서 함수의 타입을 지정할 수 있다.

- 함수가 실행되고 반환하는 데이터의 타입을 지정할 수 있다.

- 함수 타입의 인터페이스를 만들면, 동일한 구조의 함수가 있을 때 그 타입을 똑같이 지정할 수 있다.(재사용성)

- 매개변수의 이름이 달라고 무관하다.(단, 타입만 일치하다면)

- 매개변수의 갯수는 일치해야 한다.

interface GetName {
  (param: string): string;
  // 함수는 매개변수가 필요할 수 있고 매개변수는 message, message의 타입은 string.
}
// 만들어진 함수가 실행되고 나면 string 타입의 데이터를 반환한다.



interface User {
  name: string;
  age: number;
  getName: GetName;
  // getName: (message: string) => string 
}

const eddie: User = {
  name: 'Eddie',
  age: 45,
  getName(message: string) {   //함수 데이터 
    console.log(message);
    return this.name;
  }
};

heropy.getName('Hello~');

 

 

 

2.인덱스 가능 타입 - 인덱스 시그니처(Index Signature)

- 객체의 속성 이름이 동적으로 결정될 때 유용하다.

 

1. 배열

  - 배열 데이터의 타입을 지정할 수 있다.

  - 대괄호에 들어올 값의 타입을 지정할 수 있다.

 

2. 객체

  - 인터페이스로 객체데이터의 타입을 지정하는데 객체데이터에 대괄호 표기법으로 인덱싱을 해서 내용을 할당할 수 있다.

- 대괄호안에 들어갈 데이터의 별칭은 보통 key, property (자유롭게 작성 가능)

-

 

대괄호로 지정할 수 있는 인터페이스의 인덱스 가능 타입은 많이 사용하게 될 수 있는 구조

//배열
interface Fruits {
  [item: number]: string;
  // 아이템을 지정할 수 있는 키는 숫자로 이루어져 있고, 할당이 되어져 있는 값은 문자 데이터다.
}

const fruits: Fruits = ['Apple', 'Banana', 'Cherry'];
console.log(fruits[1]);
// 배열 데이터에서 아이템을 조회할 때 숫자를 넣어주면 대괄호 안의 숫자에 맞는 값을 확인 가능

// 객체
interface User {
  [key: string]: unknown;
  name: string;
  age: number;
}
// name과 age를 제외한 배열 데이터는 값을 정확하게 알 수 없다(unknown)라는 표시

const eddie: User = {
  name: 'Eddie',
  age: 85
};

eddie['isValid'] = true;
eddie['emails'] = ['eddie@gmail.com', 'keem@gmail.com'];
console.log(eddie); 
// {
//   "name": "Eddie",
//   "age": 85,
//   "isValid": true,
//   "emails": ["eddie@gmail.com", "keem@gmail.com"]
// }


interface Payload {
  [key: string]: unknown;
}

// interface User extends Payload {
//   name: string;
//   age: number;
//   isValid: boolean;
// }

// User 인터페이스에 인덱스 시그니처를 추가해 Payload 타입을 만족하게 되어 logValues함수에 전달
 interface User {
   [key: string]: unknown;
   name: string;
   age: number;
   isValid: boolean;
 }


function logValues(payload: Payload) {
  for (const key in payload) {
    console.log(payload[key]);
  }
}


const eddie: User = {
  name: 'Eddie',
  age: 85,
  isValid: true
};

logValues(eddie);

 

 

 

3.확장(상속)

- "extends" 키워드를 통해 인터페이스나 클래스를 확장(상속)할 때 사용할 수 있다.

 

- 인터페이스는 중복 정의가 가능하다.

- 인터페이스를 중복 정의할 때 속성의 타입이 일치하지 않으면 타입 오류가 발생한다.

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

interface UserB extends UserA {
  isValid: boolean;
}

const eddie: UserA = {
  name: 'Eddie',
  age: 85,
  isValid: true  // 이 줄에서 에러가 발생합니다. 
}

const sting: UserB = {
  name: 'Sting',
  age: 102,
  isValid: true
}



// 중복 정의


interface FullName {
  firstName: string;
  lastName: string;
}

interface FullName {
  middleName: string;
  lastName: boolean; // 이 줄에서 에러가 발생합니다. 
}

const fullName: FullName = {
  firstName: 'Tomas',
  middleName: 'Sean',
  lastName: 'Connery'
}


interface FullName {
  firstName: string;
  lastName: string;
}

interface ExtendedFullName extends FullName {
  middleName: string;
}

const fullName: ExtendedFullName = {
  firstName: 'Tomas',
  middleName: 'Sean',
  lastName: 'Connery'
}

 

타입 별칭(Alias)

- 'type' 키워드를 사용하여 타입에 새로운 이름을 붙이는 기능

- 타입 별칭을 사용하면 코드의 가독성을 높이고, 복잡한 타입 정의를 쉽게 관리할 수 있다.

 

기본 사용법!

- 유니언, 인터섹션, 튜플, 제네릭과 같은 여러 타입을 별칭을 통해 다양한 타입 정의 및 활용이 가능하다.

type TypeA = string; 

type TypeB = string | number | boolean;

type User = {
  name: string;
  age: number;
  isValid: boolean;
} | [string, number, boolean];

const userA: User = {
  name: 'Neo',
  age: 85,
  isValid: true
};

const userB: User = ['Evan', 36, false];


function someFunc(param: TypeB): TypeA {
  // 매개변수 'param'의 타입이 무엇인지에 따라 각 케이스의 내용을 실행
  switch (typeof param) { 
    case 'string':
      return param.toUpperCase();
    case 'number':
      return param.toFixed(2);
    default:
      return true;  // 에러가 발생한다.
  }
}

// 함수의 반환 타입이 TypeA로 정의되어 있는데, 'default'블록에서 불리언 값을 반환하려하기 때문에 에러가 발생.
// 불리언 대신 문자열을 반환하도록 수정 or 불리언 타입을 처리하도록 함수를 수정

 


 

타입 별칭과 인터페이스의 차이점!

- 타입 별칭

  • 타입 정의의 유연성을 제공하고 객체,기본,유니언,튜플 타입 등 다양한 타입을 정할 수 있다. 
  • type은 한 번 정의되면 변경할 수 없다. 즉, 동일한 이름으로 다른 type을 선언하여 속성을 추가할 수 없다.

- 인터페이스

  • 주로 객체 타입을 정의하는데 사용한다. 인터페이스는 확장이 가능하고, 동일한 이름의 인터페이스를 여러번 선언하면 자동 병합이 가능하다.
  • 구조적 서브타이핑을 지원한다. 객체의 구조가 인터페이스의 구조와 일치하면 그 객체는 그 인터페이스를 따른다.

요약하자면, 

- interface는 확장 가능, type은 확장 불가능

- interface는 주로 객체 타입에 사용하고 type은 모든 타입 정의에 사용 가능

- 객체 타입을 정의할 때는 주로 interface를, 복잡한 타입, 유니온 타입을 정의할 때는 type을 사용하는 것이 일반적이다.

 

- 두가지 개념을 주어진 상황에 맞게 적절히 사용한다면 코드의 가독성과 유지보수성을 높일 수 있다!

 

type TypeUser = {
  name: string;
  age: number;
  isValid: boolean;
}

interface InterfaceUser {
  name: string;
  age: number;
  isValid: boolean;
}

const eddie: ?? = {
  name: 'Eddie',
  age: 25,
  isValid: true
}

 

예제의 경우 타입 별칭과 인터페이스 둘 다 사용이 가능하다.

But, 굳이 하나를 꼽자면 interface를 사용할것이다.

타입 별칭은 다양한 타입을 정의할 때 유용하지만, 인터페이스는 객체의 구조를 명확하게 정의하기에 예제의 경우에는 interface를 사용하기 더 적합하다고 생각한다. 

'Typescript' 카테고리의 다른 글

tsconfig.json 구성 옵션  (0) 2024.06.10
타입스크립트 문법 (접근 제어자)  (0) 2024.06.03
타입스크립트 문법 (함수)  (0) 2024.06.02
타입스크립트 문법 (타입)  (0) 2024.05.30