-
[패캠] 타입스크립트 문법 - 인터페이스 인덱스 시그니처 (Index Signature) (9/20)Front-end 개발 2024. 2. 1. 15:33
💡 본 타입스크립트 문법 시리즈는,
패캠의 '프론트엔드 웹 개발의 모든 것 초격차 패키지 Online'에 있는 TS 강의 노트이다.현재 수강 중인 패스트캠퍼스(fastcampus, 이하 패캠) 프론트엔드 패키지 강의가 있다.
강사님은 김영웅(Heropy) 님이다.
이 글을 쓰면서 강사님의 블로그에 '한눈에 보는 타입스크립트' 자료가 있다는 것을 알게 됬다... (바보😅)
강의를 듣는데, 강의자료가 없어서 일일이 강사님이 말씀을 따라 적으면서 강의 교안(?), 강의 노트를 작성했다.
혹시나 나처럼 패캠에서 타입스립트(TypeScript)를 수강하는 사람들에게 도움이 되면 좋겠다. 🔥
09. 인터페이스 - 인덱싱 가능 타입
대표적으로 배열이나 객체 데이터의 타입을 지정할 수 있는 인터페이스의 방식이다.
이전 시간에 함수 타입을 만들 때 인터페이스 안에 소괄호(())를 사용해서 함수의 타입을 지정하는 문법을 호출 시그니처(Call Signature)를 배웠다. 같은 형에 대괄호([])를 사용하는 방식을 인덱스 시그니처(Index Signature)라고 한다.
인덱스 시그니처 : 배열
인덱스 시그니처는 대표적으로 배열 데이터의 타입을 지정할 수 있다. 배열을 정의해서 출력을 해보면, 배열의 요소의 키가 숫자로 지정되어져 있다. 여기서 볼 수 있는 키가 바로 아래 인덱스 시그니처로 정의된 인터페이스 Fruits의 item 부분이다.
interface Fruits { [item: number]: string } const fruits: Fruits = ['Apple', 'Banana', 'Cherry'] console.log(fruits[1])
배열에 들어있는 각각의 데이터들을 아이템 혹은 요소(element)라고 부른다. 아이템을 지정할 수 있는 키는 숫자로 이루어져 있으며, Fruits에서 키에 할당된 값은 문자 데이터의 형태이다.
이렇게 인터페이스를 통해서 배열 데이터의 타입을 지정할 수 있다. 배열 fruits의 숫자 1번의 키의 밸류는 바나나가 된다. 이를 fruits 배열의 1번째 아이템에 인덱싱을 한다고 표현한다.
대괄호 표기법을 사용하여 인덱싱을 할 수 있고, 그런 데이터 타입을 인터페이스로 지정할 때 인덱스 시그니처의 문법을 쓸 수 있다.
인덱스 시그니처 : 객체
호출 시그니처와 같이 시그니처 괄호 내부의 키 이름은 정해진 것이 없이 아무거나 마음껏 사용해도 된다.
아래 코드에서 User라는 이름의 인터페이스로 인덱스 할 수 있는 속성은 밑에 있는 name과 age를 제외하고는 ‘값을 정확하게 알 수 없다’라는 의미의 unkown 이라고 반환 값을 지정했다. 인덱스 시그니처를 사용하면 대괄호 표기법으로 인덱싱해서 어떤 값을 할당할 수 있다. 즉, 객체에 새로운 속성의 key-value를 추가할 수 있다.
interface User { [key: string]: unknown name: string age: number } const heropy: User = { name: 'Heropy', age: 85 } heropy['isValid'] = true heropy['emails'] = ['thesecon@gmail.com', 'test@gmail.com'] console.log(heropy)
User 인터페이스 부분에서 인덱스 시그니처 내용을 제거하면, 대괄호 표기법을 사용하여 추가적인 속성을 사용하는 코드 라인은 모두 Error가 발생한다.
정리하면, 객체 데이터에서 대괄호 표기법을 통해서 내용에 접근을 제대로 하려면 대괄호 표기법을 사용할 수 있다. 대괄호를 통해서 값을 할당하면 되는데, 타입을 명시적으로 지정해도 되지만 unknown 타입으로 어떤 데이터도 할당할 수 있도록 지정할 수 있다.
인덱스 시그니처의 매개변수는 반환값과 달리 unkown을 쓸 수 없는데, string, number, symbol, 템플릿 리터럴의 4가지 타입만 가능하다.
인터페이스의 인덱스 가능 타입이라는 것은, 어떤 배열이나 객체 데이터에 대괄호 표기법을 통해 숫자를 넣거나, 혹시 대괄호 표기법을 통해서 문자를 넣는 방식으로 인덱싱 할 수 있는 데이터 타입을 지정한다는 의미이다.
인덱스 가능 타입은 많이 사용하는 구조이기 때문에 잘 기억해두자.
인덱스 시그니처 : 인덱스 가능한 타입을 요구하는 경우
아래 코드에서 heropy라는 객체 데이터는 인터페이스 구조에 맞게 속성의 이름과 타입이 잘 작성되어 있다. 하지만 코드 마지막 줄에서 heropy 객체 데이터를 매개변수(아규먼트)로 넣어 logValues() 함수 호출하는 부분에서 Error가 발생하는 것을 볼 수 있다.
Error는 heropy라는 변수가 가지고 있는 user라는 인터페이스는 payload라는 인터페이스의 구조가 일치하지 않기 때문에 할당할 수 없기 때문에 발생한다. 구체적으로 payload랑 다르게 인덱스 시그니처 유형이 없다고 한다.
interface Payload { [key: string]: unknown } function logValues(payload: Payload) { for (const key in payload) { console.log(payload[key]) } } interface User { name: string age: number isValid: boolean } const heropy: User = { name: 'Heropy', age: 85, isValid: true } logValues(heropy) // Error
heropy 객체 데이터를 만드는 데는 User라는 인터페이스를 사용하는데 전혀 문제가 없지만, 만들어진 heropy 객체 데이터를 같은 객체 데이터처럼 보일 수 있겠지만 Payload 인터페이스에서 인덱스 가능한 타입으로 정의된 payload 매개변수 부분에 할당 할 수 없다. 즉, User라는 인터페이스도 logValues에서 인수로 사용이 되려면 인터페이스 가능 타입으로 바꿔줘야 한다.
interface Payload { [key: string]: unknown } function logValues(payload: Payload) { for (const key in payload) { console.log(payload[key]) } } interface User { [key: string]: unknown name: string age: number isValid: boolean } const heropy: User = { name: 'Heropy', age: 85, isValid: true } logValues(heropy)
타입스크립트를 다룰 때, 같은 객체 데이터를 다루더라도 인덱스 가능한 타입인지 혹은 아니지에 따라서 사용할 수 있거나 사용할 수 없을 수 있다. 인덱스 가능한 타입의 객체 데이터를 요구하는 곳에서는 할당하는 객체 데이터가 인덱스 가능한 타입일 수 있도록 인덱스 시그니처를 추가해서 제공하면 문제가 발생하지 않는다.
해당 부분도 중요한 포인트이니 잘 기억해두도록 하자.
Reference
김영웅 강사님 블로그 中 TS 파트
https://heropy.blog/2020/01/27/typescript/
김영웅 강사님 유튜브 채널
https://www.youtube.com/channel/UCcjhMpoaNvyy0StN9KgtF6w
'Front-end 개발' 카테고리의 다른 글
[패캠] 타입스크립트 문법 - 타입 별칭 (Alias) (11/20) (0) 2024.02.01 [패캠] 타입스크립트 문법 - 인터페이스 상속 (extends) (10/20) (0) 2024.02.01 [패캠] 타입스크립트 문법 - 인터페이스 호출 시그니처 (Call Signature) (8/20) (0) 2024.02.01 [패캠] 타입스크립트 문법 - 인터페이스 기본 (Interface) (7/20) (0) 2024.02.01 [패캠] 타입스크립트 문법 - 타입 가드 (6/20) (0) 2024.02.01