TypeScript - Interface, Type Aliases

박정호·2022년 10월 24일
0

TypeScript

목록 보기
2/8
post-thumbnail

⭐️ 인터페이스

인터페이스는 상호 간에 정의한 약속 혹은 규칙을 의미한다. 타입스크립트에서의 인터페이스는 다음과 같은 범주에 대해서 약속을 정의한다.

  • 객체의 스펙(속성과 속성의 타입)
  • 함수의 파라미터
  • 함수의 스펙(파라미터, 반환 타입 등)
  • 배열과 객체를 접근하는 방식
  • 클래스

👎 타입선언이 중복적인 부분들을 볼 수 있다.


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);
}

1️⃣ 변수에 대한 인터페이스

✏️ jeongho라는 변수는 User라는 타입을 가져야한다는 점을 명시적으로 작성.

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

let jeongHo: User = {
   age : 25,
   name: '정호'
}

2️⃣ 함수의 인자에 대한 인터페이스

✏️ 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);

2️⃣ 함수의 구조에 대한 인터페이스

✏️ 인터페이스에서 인자와 반환 값에 대한 타입을 설정

interface SumFunction {
    (a:number, b: number): number;
}

let sum: SumFunction;
sum = (a,b) => {
  return a + b;
}

3️⃣ 클래스에 대한 인터페이스

✏️ 타입스크립트에서도 클래스가 일정 조건을 만족하도록 타입 규칙을 정하기 가능

interface CraftBeer {
  beerName: string;
  nameBeer(beer: string): void;
}

class myBeer implements CraftBeer {
  beerName: string = 'Baby Guinness';
  nameBeer(b: string) {
    this.beerName = b;
  }
  constructor() {}
}

4️⃣ 인덱싱 & 딕셔너리 패턴

✏️ 인터페이스에서 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$/,
}

5️⃣ 인터페이스 확장

✏️ extends를 통해 Person의 값들을 상속 가능

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

interface Developer extends Person{
                
                language: string;
}

let dev: Developer = {
                age: 20,
                name: '안녕',
                language: 'C언어'
}

6️⃣ 옵션 속성

✏️ hop을 옵션 속성으로 선언하였으므로 brewBeer의 인자에 name에 대한 값만 넘기기 가능하다.

interface CraftBeer {
  name: string;
  hop?: number;  
}

let myBeer = {
  name: 'Saporo'
};
function brewBeer(beer: CraftBeer) {
  console.log(beer.name); // Saporo
}
brewBeer(myBeer);

7️⃣ 읽기 전용 속성

✏️ 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

8️⃣ 객체 선언과 관련된 타입 체킹

✏️ 타입스크립트는 인터페이스를 이용하여 객체를 선언할 때 좀 더 엄밀한 속성 검사를 진행

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;
}

⭐️ Type Aliases

타입 별칭은 특정 타입이나 인터페이스를 참조할 수 있는 타입 변수를 의미

  • 타입 별칭은 새로운 타입 값을 하나 생성하는 것이 아니라 정의한 타입에 대해 나중에 쉽게 참고할 수 있게 이름을 부여하는 개념이다.
  • VSCode 상의 프리뷰 상태로 다른 타입과 어떤 차이점이 있는지 확인이 가능하다.
  • string, number와 같은 간단한 타입 뿐만 아니라 interface 레벨의 복잡한 타입에도 별칭을 부여 가능
  • 타입 별칭에 제네릭 사용 가능
// 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로 선언해서 사용하는 것을 추천!

참고 : 캡틴판교 타입스크립트

profile
기록하여 기억하고, 계획하여 실천하자. will be a FE developer (HOME버튼을 클릭하여 Notion으로 놀러오세요!)

0개의 댓글