
인터페이스는 상호 간에 정의한 약속 혹은 규칙을 의미한다. 타입스크립트에서의 인터페이스는 다음과 같은 범주에 대해서 약속을 정의한다.
👎 타입선언이 중복적인 부분들을 볼 수 있다.
function fetchTodoItems(): {id:number,title:string,done:boolean}[] {
const todos = [
{ id: 1, title: '안녕', done: false },
{ id: 2, title: '타입', done: false },
{ id: 3, title: '스크립트', done: false },
];
return todos;
}
function addTodo(todo: {id:number,title:string,done:boolean}): void {
todoItems.push(todo);
}
function completeTodo(index: number, todo: {id:number,title:string,done:boolean}): void {
todo.done = true;
todoItems.splice(index, 1, todo);
}
👍 이 부분을 인터페이스로 간단하게 해결 가능하다.
interface Todo {
id: number;
title: string;
done: boolean;
}
function fetchTodoItems(): Todo[] {
const todos = [
{ id: 1, title: '안녕', done: false },
{ id: 2, title: '타입', done: false },
{ id: 3, title: '스크립트', done: false },
];
return todos;
}
function addTodo(todo: Todo): void {
todoItems.push(todo);
}
function completeTodo(index: number, todo: Todo): void {
todo.done = true;
todoItems.splice(index, 1, todo);
}
✏️ jeongho라는 변수는 User라는 타입을 가져야한다는 점을 명시적으로 작성.
interface User {
age: number;
name: string;
}
let jeongHo: User = {
age : 25,
name: '정호'
}
✏️ getUser의 인자는 User라는 타입을 가져야 한다.
interface User {
age: number;
name: string;
}
const getUser = (user: User) =>{
console.log(user);
}
const capt = {age: 23,name: '캡틴'}
getUser(capt);
✏️ 인터페이스에 정의된 속성, 타입의 조건만 만족한다면 객체의 속성 갯수가 더 많아도 상관없고, 인터페이스에 선언된 속성 순서를 지키지 않아도 된다.
interface User {
age: number;
// name에 대한 타입선언 X
}
const getUser = (user: User) =>{
console.log(user);
}
const capt = {age: 23,name: '캡틴'} //age에 대한 조건이 만족하므로 상관X
getUser(capt);
✏️ 인터페이스에서 인자와 반환 값에 대한 타입을 설정
interface SumFunction {
(a:number, b: number): number;
}
let sum: SumFunction;
sum = (a,b) => {
return a + b;
}
✏️ 타입스크립트에서도 클래스가 일정 조건을 만족하도록 타입 규칙을 정하기 가능
interface CraftBeer {
beerName: string;
nameBeer(beer: string): void;
}
class myBeer implements CraftBeer {
beerName: string = 'Baby Guinness';
nameBeer(b: string) {
this.beerName = b;
}
constructor() {}
}
✏️ 인터페이스에서 index는 반드시 숫자로 설정하고, value값은 string으로 설정
interface stringArray {
[index: number]: string;
}
var arr: stringArray = ['a','b','c'];
// arr[0] = '문자열';
✏️ 인터페이스 딕셔너리 패턴
interface StringRegexDictionary {
[key: string]: RegExp;
}
let obj: StringRegexDictionary = {
// sth: /abc/,
cssFile: /\.js$/,
}
✏️ extends를 통해 Person의 값들을 상속 가능
interface Person {
name: string;
age: number;
}
interface Developer extends Person{
language: string;
}
let dev: Developer = {
age: 20,
name: '안녕',
language: 'C언어'
}
✏️ hop을 옵션 속성으로 선언하였으므로 brewBeer의 인자에 name에 대한 값만 넘기기 가능하다.
interface CraftBeer {
name: string;
hop?: number;
}
let myBeer = {
name: 'Saporo'
};
function brewBeer(beer: CraftBeer) {
console.log(beer.name); // Saporo
}
brewBeer(myBeer);
✏️ readonly로 선언된 brand에 대하여 수정을 하려 하면 에러가 발생
interface CraftBeer {
readonly brand: string;
}
let myBeer: CraftBeer = {
brand: 'Belgian Monk'
};
myBeer.brand = 'Korean Carpenter'; // error!
💡 잠깐) 읽기 전용 배열
✏️ 배열을 선언할 때 ReadonlyArray 타입을 사용하면 읽기 전용 배열을 생성 가능
let arr: ReadonlyArray<number> = [1,2,3]; arr.splice(0,1); // error arr.push(4); // error arr[0] = 100; // error
✏️ 타입스크립트는 인터페이스를 이용하여 객체를 선언할 때 좀 더 엄밀한 속성 검사를 진행
interface CraftBeer {
brand?: string;
}
function brewBeer(beer: CraftBeer) {
// ..
}
brewBeer({ brandon: 'what' }); //brand이 아닌 brandon으로 error
✏️ 만약 이런 타입 추론을 무시하고 싶다면 아래와 같이 선언
let myBeer = { brandon: 'what' }';
brewBeer(myBeer as CraftBeer);
✏️ 그럼에도 불구하고 만약 인터페이스 정의하지 않은 속성들을 추가로 사용하고 싶을 때는 아래와 같은 방법을 사용
interface CraftBeer {
brand?: string;
[propName: string]: any;
}
타입 별칭은 특정 타입이나 인터페이스를 참조할 수 있는 타입 변수를 의미
// string 타입을 사용할 때
const name: string = 'capt';
// 타입 별칭을 사용할 때
type MyName = string;
const name: MyName = 'capt';
// 복잡한 타입에도 별칭을 부여
type Developer = {
name: string;
skill: string;
}
// 제네릭 사용
type User<T> = {
name: T
}
✅ 인터페이스로 선언한 타입을 프리뷰로 확인

✅ 타입 별칭으로 선언한 타입을 프리뷰로 확인

👍 type vs interface
타입 별칭과 인터페이스의 가장 큰 차이점은 타입의 확장 가능 / 불가능 여부이다. 인터페이스는 확장이 가능한데 반해 타입 별칭은 확장이 불가능하다.
따라서, 가능한한 type 보다는 interface로 선언해서 사용하는 것을 추천!
참고 : 캡틴판교 타입스크립트