[TypeScript] object index signatures

2023. 1. 2. 13:05TypeScript

⚡️object 자료에 타입을 미리 만들어주고 싶은 경우

1. object 자료에 어떤 속성들이 들어올 수 있는지 아직 모르는 경우
2. 타입지정할 속성이 너무 많은 경우
index signatures 를 사용하면 편리합니다.

 

⚡️index signatures

object 용 타입을 하나 만들고 싶습니다.

근데 아직 어떤 속성이 들어올지 모르는 경우 index signatures 사용

interface StringOnly {
  [key: string]: string
}

let obj :StringOnly = {
  name : 'kim',
  age : '20',
  location : 'seoul'
}

1. StringOnly 라는 interface를 하나 만들었습니다.

2. 근데 안에 타입을 적을 때 [어쩌구 : string] : string 이렇게 적으면

3. 모든 string으로 들어오는 key값에 할당되는 value는 string 이어야합니다~ 라는 타입이 됩니다. 

4. 쉽게 말하면 { 모든속성 : string } 이라는 뜻과 동일합니다.

5. 이제 이 object에 들어오는 모든 속성은 우측에 string을 가져야합니다.

6. 코드 한 줄로 모든 속성 타입지정이 가능해서 편리할 수 있습니다. 

 

interface StringOnly {
  age : number,   ///에러남 ㅅㄱ
  [key: string]: string,
}

interface StringOnly {
  age : string,   ///가능  
  [key: string]: string,
}

[ ] 이 문법은 다른 속성과 함께 사용할 수 있지만

{ 모든 속성 : string, age : number } 이건 뭔가 논리적으로 말이 되지 않아 금지시킵니다.

 

interface StringOnly {
  age : number,   ///가능
  [key: string]: string | number,
}

이건 가능합니다. 

{ 모든속성 : string | number, age : number } 이렇게 해주면 논리적으로 말이 됩니다.

 

⚡️array 형태도 가능

자바스크립트에서 array와 object는 크게 다를게 없는 같은 자료형입니다. 

let obj = {
  0 : 'kim'
  1 : '20',
  2 : 'seoul'
}
console.log(obj[2]) //이러면 'seoul' 출력됨  

1. 위 코드를 보면 array랑 똑같이 사용가능합니다.

2. 아무튼 object로도 array 처럼 사용가능  

(object 자료도 대괄호쳐서 안에 있는 데이터 뽑을 수 있습니다)

 

interface StringOnly {
  [key: number]: string,
}

let obj :StringOnly = {
  0 : 'kim'
  1 : '20',
  2 : 'seoul'
}

1. [ ] 여기 안에 key값의 타입을 number 로 지정할 수도 있습니다. (대괄호 안엔 string 또는 number만 가능)

2. 그럼 이제 object의 키값이 숫자로 들어오는 경우 value로 string을 가져야한다는 타입입니다. 

3. 쉽게 말하면 { 모든숫자속성 : string } 이라는 뜻과 동일합니다.

4. 그래서 array처럼 쓰고싶은 object가 있으면 저렇게 타입지정도 가능하다는 소리입니다. 

5. 숫자 key만 넣을거면 그냥 array + tuple 타입 쓰는게 더 직관적일 수 있습니다.

 

⚡️Recursive Index Signatures

(방법1)

interface MyType {
  'font-size' : {
    'font-size' : {
      'font-size' : number
    }
  }
}

let obj = {
  'font-size' : {
    'font-size' : {
      'font-size' : 14
    }
  }
}

1. object 안에 object 안에 object가 들어있습니다.

2. 직접 interface 안에 {} 이걸 3번 중첩되게 만드셔도 되긴 하지만 

3. 귀찮을 경우 이런 테크닉을 사용할 수 있습니다. 

 

(방법2) 

interface MyType {
  'font-size': MyType | number
}


let obj :MyType = {
  'font-size' : {
    'font-size' : {
      'font-size' : 14
    }
  }
}

 

1. 'font-size' 속성은 MyType 이거랑 똑같이 생겼다고 타입을 만들었습니다.

2. 그리고 object자료가 4중첩 5중첩 X중첩되어도 대응가능 


(문제1) 다음 자료의 타입을 지정해보십시오. 

let obj = {
  model : 'k5',
  brand : 'kia',
  price : 6000,
  year : 2030,
  date : '6월',
  percent : '5%',
  dealer : '김차장',
}

 

(정답)

type Car = {
  [key :string] : number | string
}

let obj :Car = {
  model : 'k5',
  brand : 'kia',
  price : 6000,
  year : 2030,
  date : '6월',
  percent : '5%',
  dealer : '김차장',
}

유연한 타입지정이 가능하지만 엄격하지 않아서

버그를 잡아준다는 장점은 없어질 수 있습니다. 

 

(문제2) 다음 object 자료의 타입을 interface 써서 만들어보십시오. 

let obj = {
  'font-size' : 10,
  'secondary' : {
    'font-size' : 12,
    'third' : {
      'font-size' : 14
    }
  }
}

(정답)

interface MyType {
  'font-size' : number,
  [key :string] : number | MyType,
}

let obj = {
  'font-size' : 10,
  'secondary' : {
    'font-size' : 12,
    'third' : {
      'font-size' : 14
    }
  }
}

1. MyType을 만들었는데 여기 안엔 'font-size' 속성, 그리고 모든 문자 속성이 들어갈 수 있습니다.

2. 모든 문자 속성이 들어오면 number | MyType을 가져야한다고 타입지정해놨습니다.

3. object 안에 object를 집어넣어도 MyType 타입과 비슷하게 생기면 통과시켜줍니다.