본문 바로가기
개인공부/Typescript 공부

Typescript 인터페이스

by 강물둘기 2023. 3. 5.

* 조시 골드버그의 러닝 타입스크립트라는 책을 읽고 정리하면서 코드를 작성해본 내용입니다.

 

인터페이스(interface)는 연관된 이름으로 객체 형태를 설명하는 또다른 방법이다.

인터페이스는 타입 별칭(type)과 유사하지만 일반적으로 더 읽기 쉬운 오류 메시지, 더 빠른 컴파일러 성능, 클래스와의 더 나은 상호 운용성을 위해 선호된다.

 

1. 타입 별칭(type) vs 인터페이스(interface)

두 구문은 거의 비슷하다.

 

차이점은 다음과 같다.

⓵ 인터페이스는 속성 증가를 위해 병합할 수 있다.(이 장 뒷부분에 설명)

    이 기능은 외부 코드(라이브러리 등)를 사용할 때 특히 유용하다. 

⓶ 인터페이스는 클래스가 선언된 구조의 타입을 확인하는 데 사용할 수 있지만 타입 별칭은 사용할 수 없다.

⓷ 일반적으로 인터페이스에서 타입 검사기가 더 빨리 작동한다. 

⓸ 인터페이스는 이름이 있는(명명된) 객체로 간주되므로 오류 메시지를 더 쉽게 읽을 수 있다.

 

가능하다면 인터페이스 사용을 권장한다.

 

2. 속성 타입

2.1 선택적 속성

타입 별칭과 마찬가지로 선택적 속성에는 ? 를 붙여서 나타낼 수 있다.

 

2.2 읽기 전용 속성

속성 앞에 readonly 키워드를 붙이면 평소대로 읽을 수는 있지만 재할당은 불가능하다.

 

readonly 제한자는 코드 영역에서 객체를 의도치 않게 수정하는것을 막는다. 하지만 컴파일 이후 자바스크립트 코드에서는 readonly 제한자가 사라진다. readonly는 단지 타입스크립트의 타입 검사기를 사용하여 개발 도중에 객체를 보호하기 위해 사용한다.

 

2.3 함수와 메서드

인터페이스를 사용하여 객체 프로퍼티 값으로 함수 타입을 선언할 수도 있다. 

두 선언방법은 자바스크립트에서 객체를 함수로 선언하는 방법과 같다.

두 선언방법의 차이점은 다음과 같다.

⓵ 메서드는 readonly로 선언할 수 없지만 일반 속성 구문은 가능하다.

⓶ 인터페이스 병합은 메서드와 일반 속성 구문을 다르게 처리한다.

⓷ 타입에서 수행되는 일부 작업은 메서드와 일반 속성 구문을 다르게 처리한다.(15장 참조)

 

2.4 호출 시그니처(Call Signature)

인터페이스와 객체 타입은 호출 시그니처로 선언할 수 있다. 호출 시그니처는 함수 타입을 설명한다.

함수 타입 선언과 비슷하지반 => 대신 : 를 사용한다.

 

호출 시그니처는 사용자 정의 속성을 추가로 갖는 함수를 설명하는데 사용할 수 있다.

호출 시그니처를 위와같이 작성했을 때 함수는 count라는 프로퍼티를 가지고 있어야 한다.

 count 프로퍼티가 없는 함수를 Func라는 호출 시그니처를 가지는 변수에 할당하면 오류가 발생한다.

 

 

2.5 인덱스 시그니처(Index Signature)

인터페이스 내에서 키의 타입을 인덱스처럼 표현할 수 있다.

객체 내에 프로퍼티 수가 확실하지 않을 때 활용할 수 있다. key가 string이고 값이 number 타입이라면 프로퍼티 개수가 몇개가 되든 상관없다.

 

* 인덱스 시그니처 사용시 주의할 점이 있다.

위와 같이 banana라는 프로퍼티를 추가했지만 값을 할당하지 않아도 타입 시스템에서 오류가 발생하지 않는다. 그러나 실제로는 undefined 라는 값을 가지고 있기 때문에 런타임에서는 toFixed 메서드 사용시 오류가 발생한다.

 

* 키/값을 저장하려고하는데 키를 미리 알 수 없다면 인덱스 시그니처보다는 Map 객체 사용을 권장한다.(9장 참조)

 

속성과 인덱스 시그니처 혼합

인터페이스에 명시적으로 선언된 속성과 포괄적으로 선언되는 인덱스 시그니처를 같이 사용할 수 있다.

이 때 명시적으로 선언된 속성은 인덱스 시그니처에 포함되어야 한다.

명시적으로 선언된 속성이 객체내에 존재하지 않으면 오류가 발생한다.

 

명시적으로 선언된 속성에 타입 리터럴을 할당할 수도 있다. 마찬가지로 이 타입 리터럴은 인덱스 시그니처에 포함되어야 한다.

 

숫자 인덱스 시그니처

인덱스 시그니처 키로 string 대신 number 타입을 사용할 수 있다. 이 때 명명된 속성은 그 타입을 포괄하는 string 인덱스 시그니처의 타입으로 할당할 수 있어야 한다.

 

2.6 중첩 인터페이스

중첩 객체처럼 인터페이스도 중첩될 수 있다.

 

 

3. 인터페이스 확장

타입스크립트는 인터페이스가 다른 인터페이스의 모든 맴버를 복사해서 선언할 수 있는 확장된 인터페이스를 허용한다. extends 키워드를 사용하여 기존에 있던 인터페이스에 확장하여 파생 인터페이스를 선언할 수 있다.

확장된 인터페이스는 기존 인터페이스가 가지고 있는 속성을 모두 가지고 있어야 한다. 

인터페이스 확장은 기존 인터페이스를 재사용하여 코드의 중복작업을 피할 수 있다.

 

3.1 재정의된 속성

확장 인터페이스에서 기존 인터페이스에 있던 속성을 다시 선언하여 재정의하거나 대체할 수 있다.

 

재정의하는 타입은 기존 속성에 포함되는 타입이어야 한다.

기존 속성에 undefined 타입은 포함되지 않기 때문에 잘못 확장했다는 오류가 생긴다.

 

3.2 다중 인터페이스 확장

인터페이스를 확장할 때 여러개의 다른 인터페이스를 확장할 수 있다. 

확장된 인터페이스는 모든 기본 인터페이스의 맴버를 받는다.

 

4. 인터페이스 병합

두 개 이상의 인터페이스가 동일한 이름으로 동일한 스코프에 선언되는 경우 선언된 모든 필드를 포함하는 더 큰 인터페이스가 코드에 추가된다.

위의 두 코드는 동일하게 동작한다.

인터페이스가 여러 곳에 선언되면 코드를 이해하기 어려워지기 때문에 인터페이스 병합은 사용을 지양해야한다.

 

* 인터페이스 병합은 외부 라이브러리를 사용하거나 Window같은 내장 전역 인터페이스를 보강할 때 유용하다.

 

4.1 이름이 충돌되는 맴버

병합된 인터페이스는 타입이 다른 동일한 이름의 속성을 여러 번 선언할 수 없다.

동일한 이름의 속성이 있는경우 같은 타입으로 선언해야 오류가 발생하지 않는다.

 

그러나 동일한 이름과 다른 시그니처를 가진 메서드는 정의할 수 있다.

이렇게 선언하면 메서드에 대한 함수 오버로드가 발생한다.

 

 

 

 

Reference

- 조시 골드버그, 러닝 타입스크립트, 고승원 옮김, 2023

- https://typescript-kr.github.io/pages/interfaces.html

'개인공부 > Typescript 공부' 카테고리의 다른 글

Typescript 타입 제한자  (0) 2023.03.11
Typescript 클래스  (0) 2023.03.09
Typescript 배열  (0) 2023.03.03
Typescript 함수  (0) 2023.03.01
Typescript 객체  (0) 2023.02.28

댓글