이슈
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] )
}
내가 짠 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()] )
}
그러나 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의 다음 글에 있는 답변이다.
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];
}
const key
에 마우스 커서를 올려보면(vscode에서) key
는 다음과 같은 값을 가질 수 있는 타입이 된 것을 알 수 있다
const key = "taMin0" | "taMin1" | "taMin2" | "taMin3"
keyof
와 typeof
2 개 모두 꼭 필요한가?
이런 경우 keyof typeof object
인 경우이고, object 대신 type을 활용한다면 keyof type
으로 약간 더 간소화할 수 있다.
const key2: keyof IAbc =
('taMin' + i.toString()) as keyof IAbc;
sample[key2];
위의 예제에서 for
문 대신 map
을 사용해도 동일한 오류가 발생한다
Object.keys(sample).map((key, i) => {
sample[key]
})
역시 type assertion
을 해줘야 한다.
Object.keys(sample).map((key, i) => {
const specialKey: keyof IAbc =
key as keyof IAbc;
sample[specialKey];
})
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])
})
소시적 C 언어 프로그래밍을 많이 했기 때문에 정적 타입 언어는 금방 적응하겠지 싶었으나, Typescript는 그리 만만치가 않다.
Photo by Leighann Blackwood on Unsplash
Top comments (0)