230606.til

Universe·2023년 6월 6일
0

타입스크립트 핸드북 스터디 2

타입스크립트의 interface 키워드는
두개의 시스템 상호간의 약속 또는 규칙 을 의미한다.
틀, 설계도 라고 생각하면 쉽다.
함수나 객체가 일정한 '틀'을 가진다면, interface 를 통해
일관적인 '틀' 의 규격을 맞추어 예상 가능한 객체나 함수를 만들 수 있도록 도움을 준다.
interface 는 다음과 같은 범주에 대해 약속을 정의할 수 있다.

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

1. 객체의 형태 정의

interface Car {
  make: string;
  model: string;
  year: number;
}

const myCar: Car = {
  make: 'Toyota',
  model: 'Corolla',
  year: 2005
};

2. 함수의 형태 정의

interface GreetFunction {
  (name: string, age: number): string;
}

const greet: GreetFunction = (name, age) => {
  return `Hello ${name}, you are ${age} years old.`;
};

3. class

interface Animal {
  name: string;
  species: string;
  sound(): void;
}

class Dog implements Animal {
  name: string;
  species: string;

  constructor(name:string, species:string = "Dog"){
    this.name = name;
    this.species = species;
  }

  sound(): void {
    console.log("멍")
  }
}

const 멍멍이:Animal = new Dog("멍멍이")
멍멍이.sound();

클래스가 특정 조건을 충족하도록 강제할 수 있다.
implement 키워드를 사용한다.
멍멍이 class 는 반드시 Animal interface 에 명시된 속성과 메소드를 가져야만 한다.

선택적 프로퍼티

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

const Soo: User = {
  name: 'soo',
  age: 20
}

const Woo: User = {
  name: "Woo",
  age: 21,
  email: "abc@gamil.com"
}

interface 에 '?' 를 붙혀서 선언해 주는 것으로
프로퍼티를 선택적으로 만들 수 있다.
User interface 를 받는 객체는 name, age 프로퍼티를 필수로 갖지만
email 프로퍼티는 선택적으로 설정할 수 있다.

readonly

값의 속성이 "읽기 전용" 이라는 것을 명시해준다.
컴파일 단계에서 초기화 이후에 값을 변경할 수 없다는 것을 명시해 주기 위한 옵션.

interface ReadonlyPerson {
  readonly name: string;
  readonly age: number;
}

let p1: ReadonlyPerson = { name: 'John', age: 30 };

p1.name = "jon" // 읽기 전용 속성이므로 'name'에 할당할 수 없습니다.

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

let arr: ReadonlyArray<number> = [1,2,3];
arr.push(4) // readonly number[] 형식에 'push' 속성이 없습니다.

interface & type alias

type alias 는 '타입 별칭' 이라는 이름으로 쓰인다.
기존의 타입에 새로운 이름을 지정할 수 있는 방법.
가장 직관적으로 확인할 수 있는 type alias 가 interface 에 대비되는 장점은
VSCode 로 확인할 수 있다.

interface 와 type alias 모두 "{} 형식에 ~ 형식의 ~ 속성이 없습니다"
하는 에러 메시지를 출력하지만 interface 는 해당 타입이
어떠한 구조를 가지고 있는지 보여주지는 않는다.
두 유형 모두 자동완성 기능은 제공한다.

둘의 특징은 다음과 같다.

interface

  • 객체의 형태를 주로 설명한다. 위에서 설명한 내용과 같이 "틀" 을 만드는 것에 주요.
  • 클래스 등의 객체지향을 다루는 과정에서 구현(implements)을 강제할 수 있다.
  • typescript 내부에서 여러 선언이 자동으로 병합된다. (interface 는 여러번 선언할 수 있다.)
  • extends 키워드를 통한 상속이 가능하다.

type alias

  • 기본 타입 유형 뿐만 아니라 유니온, 튜플, 조건부 타입 등의 고급 타입을 정의할 수 있다.
  • 정확하게는 "정의한다" 가 아닌 해당 타입들의 "별칭"을 만들어 관리할 수 있다.
  • intersection 을 통해 타입의 병합이 가능하다.

둘은 비슷하지만 다음과 같은 차이점을 가지고 있다.

  • interface 는 선언 병합이 가능하지만 type alias는 불가능
interface A {
  a:number,
  b:number,
  c:number
}

interface A {
  d: number
} // 에러를 출력하지 않음

type B = {
  a: number,
  b: number,
  c: number
} // "B" 식별자가 중복되었습니다.

type B = {
  d: number
} // "B" 식별자가 중복되었습니다.
  • inteface 는 extends 를 이용한 확장이 가능하다. type alias 는 '&' 연산자를 이용하여 유사한 결과를 얻을 수 있다.
interface A {
  a:number,
  b:number,
  c:number
}

interface Aa extends A {
  d: number
}

type B = {
  a: number,
  b: number,
  c: number
}

type Bb = B & {
  d: number
}
  • type alias 를 extends 하는 것은 불가능 하지만 그 역은 가능하다.
type Jobs = 'salary worker' | 'retired';

interface Client {
  name: string;
}

interface MoreJobs extends Jobs {
  description: string;
} // 인터페이스는 개체 형식 또는 정적으로 알려진 멤버가 포함된 개체 형식의 교집합만 확장할 수 있습니다.ts(2312)


type VIPClient = Client & { benefits: Jobs};

정리
둘은 비슷하지만 대체할 수 없는 몇가지의 기능이 있다.
예를들어 선언 병합의 기능을 수행할 수 없는 type alias 만으로는
기존의 라이브러리의 타입을 확장하는 등의 기능을 수행하기 까다롭다.
반면에 조건부 타입, 타입가드 등의 고급 타입 등의 기능을 사용하여
보다 정제된 타입 시스템을 구축하는 것은 interface 만으로는 불가능하다.
요즘 추세는 type alias 를 default 로 사용하되, 필요에 따라 interface 를 이용한
확장을 추가하는 편이라고 한다.

profile
Always, we are friend 🧡

0개의 댓글