developer_kcm
타입스크립트 문법 (Interface, Alias) 본문
인터페이스(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 |