[TypeScript] Interface(인터페이스)란 무엇일까?
(Interface) 인터페이스란?
- 인터페이스는 일반적으로 타입 체크를 위해 사용되며 변수, 함수, 클래스에 사용할 수 있다.
- 타입스크립트의 인터페이스는 두 개의 시스템 사이에 상호 간에 정의한 약속 혹은 규칙을 포괄하여 의미한다.
- 혹은 객체의 껍데기 또는 설계도라고 할 수 있다.
❗️즉, 프로그래밍에서 클래스 또는 함수의 '틀'을 정의하는 것처럼, 타입의 '틀'로서 사용할 수 있는 것이 인터페이스인 것이다.
⚠️그러나
인터페이스는 프로퍼티와 메소드를 가질 수 있다는 점에서 클래스와 유사하나 직접 인스턴스를 생성할 수 없고❌ 모든 메소드는 추상 메소드이다.
이번 포스팅은 인터페이스의 종류에 대해 일부 포스팅을 해보겠다.
선택적 프로퍼티(Optional Properties)
인터페이스를 사용할 때 인터페이스에 정의되어 있는 속성을 반드시 모두 다 꼭 사용해야 한다면 코드의 유연성이 사라지기 마련이다.
너무 하나하나씩 따지면 일일이 구조마다 인터페이스를 생성해야 할지도 모른다.
🙌🏻 선택적 프로퍼티(Optional Properties)는 이를 해결할 수 있는 간편한 연산자이다.
콜론(:) 앞에 물음표(?)를 붙이면 이 속성은 옵션 속성이 되고,?를 붙이며 생략하여도 에러가 발생하지 않는다.
ex) user?: string;
- 예시 1
interface Users {
userEmail: string;
password: string;
age? : number;
address?: string;
}
const users: Users = {
userEmail: 'banana@gmail.com',
password: '1234'
}
console.log(users); // 에러 발생하지 않음❌
- 예시 2
interface Users {
name: string;
age: number;
gender?: string;
}
let user: Users = {
name: 'celine',
age: 20,
};
user.age = 10;
user.gender = "female"; // 선택적 프로퍼티에 의해서 나중에 속성값을 넣어줄수도 있다.
user.hight = ''; // ⚠️아예 정의되지도 않는 속성을 마음대로 집어넣을 수는 없다.
읽기 전용 프로퍼티(Readonly properties)
읽기 전용 속성은 인터페이스로 객체를 처음 생성할 때만 값을 할당하고 그 이후에는 변경할 수 없는 속성을 의미한다.
readonly 속성을 앞에 붙이면 간단하게 적용된다.
interface Score {
readonly x: number;
readonly y: number;
}
인터페이스로 객체를 처음 선언하여 값을 대입할 때는 문제가 없다.
❗️그러나 그 후에 따로 프로퍼티에 접근해서 수정하려고 하면 오류가 나게 된다.
interface User {
name: string;
age: number;
gender?: string;
readonly birth: number; // 읽기 전용 속성
}
let user: User = {
name: 'celine',
age: 20,
birth: 0719, // 최초에 값을 초기화 할때만 할당이 가능
};
user.birth = 0701; // Error🚫 -> 이후에는 수정이 불가능
readonly VS const
readonly와 const 는 처음 초기화 할 때만 값을 선언하고, 그 후에는 값을 수정하지 못한다는 점에서 유사하다.
다만❗️ 이 둘은 사용처가 다른데, 변수는 const를 쓰고 프로퍼티는 readonly를 사용된다는 점만 기억하면 된다.
readonly 활용
만약 모든 속성이 readonly일 경우?
👉🏻 일일히 프로퍼티마다 readonly를 찍어주지 말고, 따로 Utility(유틸리티)나 Assertion(단언)타입을 활용해 구현이 가능하다!!
- Only readonly
// readonly 무자비로 추가
interface User {
readonly name: string,
readonly age: number
}
let user: User = {
name: 'Park',
age: 20
};
user.age = 30; // Error🚫
user.name = 'Kim'; // Error🚫
- readonly Utility
// Readonly Utility 활용
interface User {
name: string,
age: number
}
let user: Readonly<User> = { // Array 처럼 따로 Readonly 라는 자료형이 있다고 생각하면 된다
name: 'Park',
age: 20
};
user.age = 30; // Error🚫
user.name = 'Kim'; // Error🚫
- Type Assertion
// Assertion 타입
let user = {
name: 'Park',
age: 20
} as const; // 따로 인터페이스를 사용하지 않고 객체 데이터 자체에 'as const'를 붙이게 되면 이 자체가 리터럴 타입이 된다.
user.age = 30; // Error🚫
user.name = 'Kim'; // Error🚫
인터페이스 확장(extends)
- class와 같이 인터페이스도 인터페이스 간 확장이 가능하다.
자바스크립트 클래스에서 상속을 할 때 키워드를 사용하는데 그대로 인터페이스에서도 사용해 주면 된다!!
- Interface
// Interface
interface Person {
name: string;
}
interface Worker extends Person {
job: string;
}
let fe: Worker = { name: 'Park', job: 'Developer' };
- Type
// Type
type Person = { name: string };
type Worker = Person & { job: string };
let fe: Worker = { name: 'Pakr', job: 'Developer' };
❗️특이한 점은 인터페이스 확장은 여러 개의 extends가 가능하다는 점이다. (클래스는 반드시 하나만 extends 할 수 있다)
ex) interface Worker extends Person, ooo{...}
인터페이스 함수 타입
- 인터페이스는 JavaScript 객체가 가질 수 있는 넓은 범위의 형태를 기술할 수 있다.
- 프로퍼티로 객체를 기술하는 것 외에, 인터페이스는 함수 타입을 설명할 수 있는데,
👉🏻 그러기 위해서 인터페이스에 호출 서명 (call signature)를 전달한다. 이는 매개변수 목록과 반환 타입만 주어진 함수 선언과 비슷하다. ❗️각 매개변수는 이름과 타입이 모두 필요하다.
호출 시그니처 (call signature)
interface SearchFunc {
(source: string, subString: string): boolean;
}
한번 정의되면, 함수 타입 인터페이스는 다른 인터페이스처럼 사용할 수 있다. 여기서 함수 타입의 변수를 만들고, 같은 타입의 함수 값으로 할당하는 방법을 보여준다.
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
올바른 함수 타입 검사를 위해, 매개변수의 이름이 같을 필요는 없다. 예를 들어, 위의 예제를 아래와 같이 쓸 수 있다.
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1;
}
함수 매개변수들은 같은 위치에 대응되는 매개변수끼리 한 번에 하나씩 검사한다.
let mySearch: SearchFunc;
mySearch = function(src, sub) {
let result = src.search(sub);
return result > -1;
}
함수 표현식이 숫자 나 문자열을 반환했다면, 타입 검사는 반환 타입이 SearchFunc 인터페이스에 정의된 반환 타입과 일치하지 않는다는 에러를 발생시킨다.
let mySearch: SearchFunc;
// error: Type '(src: string, sub: string) => string' is not assignable to type 'SearchFunc'.
// Type 'string' is not assignable to type 'boolean'.
mySearch = function(src, sub) {
let result = src.search(sub);
return "string";
};
👉🏻 이 외에도 종류는 더 있지만 포스팅은 일단 여기까지! 추후에 더 추가해보려고 한다. 🖐🏻
참고
https://velog.io/@soulee__/TypeScript-Interface-2
https://poiemaweb.com/typescript-interface
https://inpa.tistory.com/entry/TS-📘-타입스크립트-인터페이스-💯-활용하기