-
TypeScript | Interface 인터페이스JavaScript/TypeScript 2020. 5. 7. 12:34
Interface 인터페이스
타입스크립트에서 인터페이스는 여러 가지 자료형의 타입을 정의하는 용도로 사용
인터페이스로 객체 타입 정의하기
interface 키워드를 사용해서 인터페이스로 타입 정의
interface Person { name: string; age: number; } const p1: Person = { name: 'mike', age: 23 }; const p2: Person = { name: 'mike', age: 'ten' }; // 타입 에러
- Person 인터페이스로 객체 내부에 존재하는 각 속성의 타입 정의
- 하나 이상의 속성 타입을 만족하지 못하면 타입 에러 발생
선택 속성
선택 속성은 객체에 없어도 되는 속성을 말함
인터페이스에서 선택 속성은 ?(물음표) 기호 사용interface Person { name: string; age?: number; } const p1: Person = { name: "mike" }; // 선택 속성 대신 유니온 타입으로 undefined를 추가하는 경우 interface Person { name: string; age: number | undefined; } const p1: Person = { name: "mike" }; // 타입 에러 const p2: Person = { name: "mike", age: undefined };
- 유니온 타입으로 undefined를 추가하는 경우 선택 속성과 달리 명시적으로 undefined를 입력해야 함
읽기 전용 속성
읽기 전용 속성은 값이 변하지 않는 속성을 말함
인터페이스에서 읽기 전용 속성은 readonly 키워드 사용interface Person { readonly name: string; age?: number; } const p1: Person = { name: 'mike', } p1.name = 'jonh'; // 컴파일 에러
- 변수를 정의하는 시점에는 값 할당 가능
- 읽기 전용 속성의 값을 수정하려고 하면 컴파일 에러가 발생함
정의되지 않은 속성값을 할당하는 경우
보통은 객체가 인터페이스에 정의되지 않은 속성값을 갖고 있어도 할당이 가능하지만
리터럴로 초기화하는 경우에는 타입 에러 발생interface Person { readonly name: string; age?: number; } // 리터럴로 초기화하는 경우 const p1: Person = { name: 'mike', birthday: '1997-01-01', // 타입 에러 } const p2 = { name: 'mike', birthday: '1997-01-01', } const p3: Person = p2;
- Person 인터페이스에 정의되지 않은 birthday 속성을 리터럴로 입력하므로 타입 에러 발생
→ 리터럴에서 에러가 발생하는 이유는 프로그래머의 실수일 확률이 높기 때문이며, 이는 타입스크립트의 편의 기능임 - p2는 Person에 정의되지 않은 속성을 포함하지만 p3에 할당될 때 타입 에러가 발생하지 않음
→ p3 타입이 p2의 타입을 포함하는 더 큰 타입이기 때문('타입 호환성'에서 다룸)
인터페이스로 인덱스 타입 정의하기
인터페이스에서 속성 이름을 구체적으로 정의하지 않고 값의 타입만 정의하는 것을 인덱스(index) 타입이라고 함
interface Person { readonly name: string; age: number; // 인덱스 타입 [key:string]: string | number; } const p1: Person = { name: 'mike', birthday: '1997-01-01', age: '25', // 타입 에러 }
- 문자열로 된 속성 이름에 대해 값이 문자열 또는 숫자라고 정의
- birthday 속성을 리터럴로 정의해도 컴파일 에러가 발생하지 않음
- age는 명시적으로 숫자로 정의했기 때문에 문자열 입력 시 타입 에러 발생
여러 개의 인덱스를 정의하는 경우
자바스크립트에서는 속성 이름에 숫자와 문자열을 사용할 수 있는데,
속성 이름이 숫자인 경우 문자열로 변환된 후 사용됨
따라서 타입스크립트에서는 숫자인 속성 이름의 값이 문자열인 속성 이름의 값으로 할당 가능한지 검사interface YearPriceMap { [year: number]: number; [year: string]: string | number; } const yearMap: YearPriceMap = {}; yearMap[1998] = 1000; yearMap[1998] = 'abc'; // 타입 에러 yearMap['2000'] = 1234; yearMap['2000'] = 'million';
- YearPriceMap 에서 number 는 string | number에 할당 가능하기 때문에 타입 에러가 발생하지 않음
- 숫자인 속성 이름이 문자열로 변환되기 때문에 숫자 속성의 값이 문자 속성의 값에 포함될 수 있어야 하는 것
- 속성 이름이 숫자인데 문자열을 값으로 입력하면 타입 에러 발생
인터페이스로 함수 타입 정의하기
인터페이스로 함수를 정의할 때는 속성 이름 없이 정의
interface GetInfoText { (name: string, age: number): string; } const getInfoText: GetInfoText = function(name, age) { const nameText = name.substr(0, 10); const ageText = age >= 35 ? 'senior' : 'junior'; return `name: ${nameText}, age: ${ageText}`; }
인터페이스로 클래스 구현하기
implements 키워드를 사용해서 인터페이스를 클래스로 구현
interface Person { name: string; age: number; isYoungerThan(age: number): boolean; } class SomePerson implements Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } isYoungerThan(age: number) { return this.age < age; } }
- 세 개의 속성을 가진 인터페이스 정의
- implements 키워드를 이용해서 인터페이스를 클래스로 구현
- 하나의 속성이라도 구현하지 않으면 컴파일 에러 발생
- name, age 속성은 필수 속성이기 때문에 생성자에서 값을 할당하지 않으면 컴파일 에러 발생
※ 타입스크립트에서 클래스의 타입을 정의하기 위해서는 알아야할 내용이 많지만
리액트에서는 객체지향 프로그래밍을 할 일이 많지 않고
리액트 훅의 등장으로 클래스형 컴포넌트의 중요성이 낮아짐
인터페이스 확장
extends 키워드를 사용해서 인터페이스 확장 가능
여러 개의 인터페이스를 확장할 수도 있음interface Name { name: string; } interface Age { age: number; } interface Korean extends Name, Age { isLiveInSeoul: boolean; } /* interface Korean { name: string; age: number; isLiveInSeoul: boolean; } */
- Name, Age 인터페이스를 확장해서 Korean 인터페이스 생성
- 확장해서 만들어진 Korean 인터페이스는 주석 처리한 것과 같음
인터페이스 합치기
& 기호(교차 타입)를 사용해서 여러 인터페이스를 하나로 합칠 수 있음
interface Person { name: string; age: number; } interface Product { name: string; price: number; } type PP = Person & Product; const pp: PP = { name: 'a', age: 23, price: 1000, }
- type PP는 합쳐진 두 인터페이스 Person과 Product의 모든 속성값을 포함
- PP의 타입이 name 속성만 포함하지 않는 것은 PP 타입이 Person과 Product 속성의 교집합이 아니라
각 인터페이스의 타입이 가질 수 있는 값의 집합에 대한 교집합이기 때문
참고도서: [실전 리액트 프로그래밍 / 저자_ 이재승 / 출판사_ 프로그래밍 인사이트]
'JavaScript > TypeScript' 카테고리의 다른 글
TypeScript | 타입 호환성 (0) 2020.05.07 TypeScript | 함수형 타입 (0) 2020.05.06 TypeScript | Enum 열거형 타입 (0) 2020.05.06 TypeScript | 개요 & 변수 타입 (0) 2020.05.06