(TS) Interface

Mirrer·2022년 12월 25일
0

TypeScript

목록 보기
4/14
post-thumbnail

Interface

상호 간에 정의한 약속 혹은 규칙

Interface객체 지향 프로그래밍(Object-Oriented Programming)에서 사용되는 개념으로 멤버에 대한 기본 구현을 정의할 수 있다.

Typescript에서 Interface는 보통 다음과 같은 범주에 대한 약속을 정의한다.

  • 객체의 스펙(속성과 속성의 타입)

  • 함수의 파라미터

  • 함수의 스펙(파라미터, 반환 타입 등)

  • 배열과 객체를 접근하는 방식

  • 클래스


아래 logName 함수의 인자는 age를 속성으로 갖는 객체이며, 인자를 받을 때 객체의 속성 타입까지 정의할 수 있다.

let fruits = { name: 'apple', price: 10 };

function logName(obj: { name: string }) {
  console.log(obj.name); // apple
}

logAge(person); // apple

위의 코드를 Interface로 변환하면 이제는 logName 함수의 인자가 더 명시적으로 변경된다.

즉, logName 함수의 인자는 FruitName이라는 타입을 반드시 가져야한다.

interface FruitName {
  name: string;
}

function logName(obj: FruitName) {
  console.log(obj.name);
}

let fruit = { name: 'apple', price: 10 };
logAge(fruit);

Interface 코드를 확인해보면 다음과 같이 추론할 수 있다.

Interface를 인자로 받아 사용할 때 항상 Interface 속성 갯수와 인자로 받는 객체의 속성 갯수를 일치시키지 않아도 된다.

즉, Interface정의된 속성, 타입의 조건만 만족하면 객체의 속성 갯수가 더 많아도 상관 없다는 의미이다.


Interface Option

위에서 설명했듯 Interface를 사용할 때 정의되어 있는 속성을 모두 사용하지 않아도 된다.

이를 옵션 속성이라고 하며, 속성 끝에 '?'를 붙여 사용한다.

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

let myName = {
  name: 'Mirrer'
};
  
function logName(name: Person) {
  console.log(beer.name); // Mirrer
}
  
logName(myName);

Readonly

Rreadonly, 읽기 전용 속성은 객체 생성 이후 값을 변경할 수 없는 속성을 의미한다.

읽기 전용 속성은 아래와 같이 readonly 키워드를 사용하며, Interface객체를 선언한 뒤 수정하려고 하면 아래와 같이 오류가 발생한다.

interface Person {
  readonly name: string;  
}

let myName: Person = {
  name: 'Mirrer'
};

myName.name = 'Change Mirrer'; // error!

Readonly Array

배열을 선언할 때 ReadonlyArray<T> 타입을 사용하면 읽기 전용 배열을 생성할 수 있다.

let numbers: ReadonlyArray<number> = [1, 2, 3];

arr.push(4); // error
arr[0] = 10; // error

Object Type Checking

TypescriptInterface를 이용하여 객체를 선언할 때 좀 더 자세한 속성 검사를 수행한다.

아래 코드를 확인해보면 Person Interfacename 속성을 선언했다.

하지만 logName 함수는 인자로 넘기는 객체에 names가 선언되어 있어 오탈자 점검을 요하는 오류가 발생한다.

interface Person {
  name: string;  
}

function logName(name: Person) {
  // ..
}
  
logName({ names: 'Mirrer' }); // error: Object literal may only specify known properties, but 'names' does not exist in type 'Person'. Did you mean to write 'name'?

만약 이런 타입 추론을 무시하고 싶다면 아래와 같이 선언한다.

let myName = { names: 'Mirrer' };
  
logName(myName as Person);

반대로 Interface정의하지 않은 속성들을 추가로 사용하고 싶다면 아래와 같은 방법을 사용한다.

interface Person {
  name?: string;
  [propName: string]: any;
}

Function Type

Interface함수의 타입을 정의할 때에도 사용할 수 있으며, 함수의 인자의 타입과 반환 값의 타입을 지정한다.

interface WishList {
  (name: string, count: number): boolean;
}  
  
let addItem: WishList;

addItem = function(name: string, count: number) {
  console.log(`${name}상품 ${count}개 구매했습니다.`);
  return true;
}

Class Type

TypescriptC#, Java...등의 객체 지향 언어처럼 Class가 특정 조건을 만족하는 타입 규칙을 지정할 수 있다.

interface Name {
  productName: string;  
}

class Price implements Name {
  productName: string = 'apple';
  
  logName(name: string) {
    this.productName = name;
  }
  constructor() {}
}

Interface Extends

Interface 또한 Class와 마찬가지로 확장이 가능하며, 여러 부모 Interface를 상속받을 수도 있다.

interface Apple {
  name: string;
}
  
interface Banana {
  color: string;
}
  
interface Orange extends Apple {
  price: number;
}

let fruit = {} as Orange;
  
fruit.name = 'apple';
fruit.color = 'yellow';
fruit.price = 100;  

참고 자료

TypeScript: JavaScript With Syntax For Types.
React TypeScript Tutorial for Beginners - Codevolution
타입스크립트 입문 - 기초부터 실전까지 - 장기효

profile
memories Of A front-end web developer

0개의 댓글