[ Typescript ] - object index signatures

최문길·2023년 12월 24일
0

Typescript

목록 보기
21/23

object 자료에 타입을 미리 만들어 주고 싶은데

object자료에 어떤 속성들이 들어올 수 있는지 아직 모르거나
타입지정할 속성이 매우 많다면

index signatures를 사용해보자 - 말은 어려워보여도... 익숙해지자




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 //가능
}



Recursive Index Signatures


오브젝트를 만들다보면 중첩된 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
}

0개의 댓글