DEV Community

Cover image for Typescript에서 객체의 프로퍼티를 programatically 참조하는 방법
Herbert Lim
Herbert Lim

Posted on • Edited on

Typescript에서 객체의 프로퍼티를 programatically 참조하는 방법

이슈

Javascript에서는 객체의 프로퍼티를 programatically 접근하기 위하여 대괄호 표기법 object['propertyName']을 흔히 사용한다. 다음 예제는 sample 객체의 각 프로퍼티를 sample['taMin' + i]으로 참조하는 예제이다.

const sample = { taMin0: 355, taMin1: 455, taMin2: 555, taMin3: 655, } for (let i=0; i<4; i++) { console.log( sample['taMin' + i] ) } 
Enter fullscreen mode Exit fullscreen mode

내가 짠 Javascript 프로그램에서는 이런 예가 정말 많다. Typescript 에서는 아래와 같이 IAbc 라는 인터페이스 타입을 정의하고 sample 객체를 초기화하면 될 줄 알았다.

interface IAbc { taMin0: number; taMin1: number; taMin2: number; taMin3: number; } const sample: IAbc = { taMin0: 355, taMin1: 455, taMin2: 555, taMin3: 655, } for (let i=0; i<4; i++) { console.log( sample['taMin' + i.toString()] ) } 
Enter fullscreen mode Exit fullscreen mode

그러나 tsc를 실행해보면 for 문 안의 sample['taMin' + i.toString()] 에서 다음과 같은 오류가 발생한다.

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'IAbc'. No index signature with a parameter of type 'string' was found on type 'IAbc'.

해석하자면 sample 객체의 인덱스로 준 'taMin' + i.toString()string 타입인데, 이 타입은 IAbc의 인덱스(키) 타입과 다르다는 것이다.

 

type assertion

구글링을 통해 힌트를 얻은 곳은 Stackoverflow의 다음 글에 있는 답변이다.

161

When using Object.keys(obj), the return value is a string[], whereas I want a (keyof obj)[].

const v = { a: 1, b: 2 } Object.keys(v).reduce((accumulator, current) => { accumulator.push(v[current]); return accumulator; }, []); 

I have the error:

Element implicitly has an 'any' type because type '{ a…

 

요지는 type assertion을 사용해야 한다는 것.


위 Stackoverflow 의 답변대로 keyof typeof 를 이용하여 아래와 같이 해결할 수 있다. 좌측의 상수 key 의 타입도 지정하고 오른쪽의 값도 동일한 타입으로 지정한다.

for (let i=0; i<4; i++) { const key: keyof typeof sample = ('taMin' + i.toString()) as keyof typeof sample; sample[key]; } 
Enter fullscreen mode Exit fullscreen mode

const key 에 마우스 커서를 올려보면(vscode에서) key는 다음과 같은 값을 가질 수 있는 타입이 된 것을 알 수 있다

const key = "taMin0" | "taMin1" | "taMin2" | "taMin3"

 

keyoftypeof 2 개 모두 꼭 필요한가?

이런 경우 keyof typeof object 인 경우이고, object 대신 type을 활용한다면 keyof type 으로 약간 더 간소화할 수 있다.

 const key2: keyof IAbc = ('taMin' + i.toString()) as keyof IAbc; sample[key2]; 
Enter fullscreen mode Exit fullscreen mode

위의 예제에서 for 문 대신 map 을 사용해도 동일한 오류가 발생한다

Object.keys(sample).map((key, i) => { sample[key] }) 
Enter fullscreen mode Exit fullscreen mode

역시 type assertion을 해줘야 한다.

Object.keys(sample).map((key, i) => { const specialKey: keyof IAbc = key as keyof IAbc; sample[specialKey]; }) 
Enter fullscreen mode Exit fullscreen mode

Typescript에서 오류가 발생하지 않는 정상적인 전체 소스코드 예는 다음과 같다.

interface IAbc { taMin0: number; taMin1: number; taMin2: number; taMin3: number; } const sample: IAbc = { taMin0: 355, taMin1: 455, taMin2: 555, taMin3: 655, } for (let i=0; i<4; i++) { const key2: keyof IAbc = ('taMin' + i.toString()) as keyof IAbc; console.log(sample[key2]) } Object.keys(sample).map((key, i) => { const specialKey: keyof IAbc = key as keyof IAbc; console.log(sample[specialKey]) }) 
Enter fullscreen mode Exit fullscreen mode

소시적 C 언어 프로그래밍을 많이 했기 때문에 정적 타입 언어는 금방 적응하겠지 싶었으나, Typescript는 그리 만만치가 않다.

Photo by Leighann Blackwood on Unsplash

Top comments (0)