Typescript 는 string 타입의 key 를 허용하지 않는다. (String Literal 또는 number 타입만 허용된다.)
따라서 아래 코드의 경우 Type 에러가 발생한다.
const friends = {
peach: 'peach',
neo: 'chico',
lion: 'lion',
};
for (const key in friends) {
// TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ peach: string; neo: string; lion: string; }'.
// No index signature with a parameter of type 'string' was found on type '{ peach: string; neo: string; lion: string; }'.
console.log(charctors[key]); // Compile Error
}
객체에 동적으로 속성을 할당하거나 key로 접근하려는 경우 객체의 형태에 따라 아래와 같이 적용할 수 있다.
interface Friends {
[key: string]: string; // key 의 타입, value 의 타입만 정의
}
for (const key in friends) {
console.log(friends[key]);
}
type nameTypes = 'peach' | 'neo' | 'lion'; // 이렇게 key 값이 정해져있을 때
type Friends = {
[name in nameTypes]: string;
};
const friends: Friends = {
peach: 'peach',
neo: 'neo',
lion: 'lion',
};
for (const key in friends) {
const name = key as nameTypes; // Type Assertion 필요함
console.log(friends[name]);
}
type nameTypes = 'peach' | 'neo' | 'lion';
type Friends = Record<nameTypes, string>; // key:nameTypes, value:string
const friends: Friends = {
peach: 'peach',
neo: 'neo',
lion: 'lion',
};
for (const key in friends) {
const name = key as nameTypes; // Type Assertion 필요함
console.log(friends[name]);
}
// 예를 들어 이런 형태로 정의하고 싶음
interface Firends {
type: string;
count: number;
// union으로 정의된 유형들
peach: string;
neo: string;
lion: string;
}
// 방법(1) 활용 방식: 이렇게는 불가~!
type Friends = {
type: string; // TS7061: A mapped type may not declare properties or methods.
count: number;
[name in nameTypes]: string;
};
// 방법(2) 활용 방식: 이렇게는 가능!
type nameTypes = 'peach' | 'neo' | 'lion';
type FriendsRecord = Record<nameTypes, string>;
interface Friends extends FriendsRecord {
type: string;
count: number;
}