object 자료에 타입을 미리 만들어 주고 싶은데
object자료에 어떤 속성들이 들어올 수 있는지 아직 모르거나
타입지정할 속성이 매우 많다면
index signatures를 사용해보자 - 말은 어려워보여도... 익숙해지자
Q . object 타입을 만들 때 key 값은 타입이 뭐다?
A . string 이다.
그런고로 이렇게 작성해보자
interface A {
[key:string] : string
}
let obj : A = {
name: 'choi',
age : '20',
married : 'no'
}
이렇게 편리할 수 가없다 .
interface의 key값에 [ 작명 : string ] : string 이렇게 적으면 모든 string으로 들어오는 key값에 할당되는 value는 string이어야 한다라는 타입이 된다.
쉽게 말하면 { 모든속성 : string } 이라는 뜻과 동일하다.
주의 할 점은
interface A {
age: number // 오류
[key : string] : string
}
interface B {
age: string // age는 반드시 들어옵니다라고 이야기하는 것
[key:string] : string
}
age는 number 타입을 가지고 싶게 하고 싶으면?
interface A {
[key : string ] : string | number
age: number //가능
}
오브젝트를 만들다보면 중첩된 Object를 만들일이 많다. 아니면
오브젝트 안에 배열, 배열안에 오브젝트를 만들거나 할 일이 많다 .
let obj = {
'font-size' : {
'font-size' : {
'font-size' : 14
}
}
}
이렇게 중첩된 object들을 한 번에 타입지정하려면 이렇게 재귀적으로 타입을 지정해 버릴 수가 있다 .
interface A {
'font-size' : A | number
}
let obj : A = {
'font-size' : {
'font-size' : {
'font-size' : 14
}
}
}
이걸 조금더 와닿게 풀어서 보자면...
interface A {
'font-size' : A | number
}
let obj : {
'font-size' : A | number // 여기서 A라는 interface에 걸리므로 (A = {..})
} = {
'font-size' : {
'font-size' : { ... }
}
}
let obj : {
'font-size' : {
'font-size' : {
'font-size' : A | number // 여기서 number에 걸리므로 number가 된다.
}
}
} = {
'font-size' : {
'font-size' : {
'font-size: 14
}
}
}
이렇게 재귀적으로 타입이 호출되는 마법을 우린 눈으로 볼 수 있었다.
조금 응용해보면
let obj = {
'font-size' : 10,
'secondary' : {
'font-size' : 12,
'third' : {
'font-size' : 14
}
}
}
이 객체의 타입을 재귀적으로 만들어 본다면 + Index Signatures
interface A {
[key:string] : A | number
}
let obj : A = {
'font-size' : 10,
'secondary' : {
'font-size' : 12,
'third' : {
'font-size' : 14
}
}
}
이렇게 해볼 수 가 있겠다.
중첩되는 객체와 배열이 있다면
interface C {
[key:string] : C | string | number | C[]
}
let user_info :C = {
id: 1234,
email: "string",
work : {
post : 'string'
},
posts: [
{ title: "string", context: "string", created_At: 12345, id: 123455 },
],
};
이렇게도 해볼 수 가 있겠는데... 사실 좋은 recursive 인지는 모르지만
암튼 시도해보는 것이 중요하니깐!!
그리고
object 의 for/in 문에 관해서 잠시 생각해보면
for/in문은 객체의 모든 열거할 수 있는 프로퍼티 (enumerable properties)를 순회할 수 있도록 해준다 .
var obj = {
name: 'choi',
age: 30,
married: false
}
for (const key in obj) {
console.log(key) // 'name' , 'age' , 'married'
console.log(obj[key]) // 'choi' , 30 , false
}
위와 같이 키워드 in
이라는 것을 응용해서 index signatures를 사용 할 수도 있다.
type LiteralKey= 'name' | 'age' | 'married';
type Obj = {
[key in LiteralKey ] : string
}
var obj : Obj = {
name: 'choi',
age: '30',
married: 'no'
}
번외로
갑자기 generic응용해보고 싶어서 해봤다....
type Sample = {
name: string,
age: number,
married: boolean
}
type Obj<T> = {
[key in keyof T] : T[keyof T]
}
var obj : Obj<Sample> = {
name: 'choi',
age: 1,
married: false
}