개발/Today I Learned

TypeScript: NestedKeysType 만들어 사용하기

devmomori 2022. 4. 9. 23:26

아래와 같은 객체에서 "B" | "C" | "D" | "G" | "H" | "A" | "E" 와 같은 Union Type을 추출하려면 어떻게 해야 할까요?

 

원하는 값을 얻기 위해서 꽤 긴 시간을 삽질을 한 것 같아요.

 

저는 단순히 TypeScript에서 제공하는 keyof 라는 값과 ValueOf 라는 제네릭 타입을 만들어서 조합하면 원하는 결과가 나올 것이라 생각했습니다.

 

Example Object which has 2 depth

 

 "B" | "C" | "D" | "G" | "H" | "A" | "E" 타입을 추출하는 것은 쉽지 않더군요.

 

먼저 fisrtsecond 객체를 뽑아내기 위하여 아래와 같은 ValueOf<T> 라는 제네릭 타입을 만들어 주었습니다.

 

type ValueOf<T> = T[keyof T];
 

해당 타입을 활용하면 결과는 이렇습니다.

 

Example Type에서 first와 second를 추출

 

이제 ExampleValues 라는 타입을 가지고  "B" | "C" | "D" | "G" | "H" | "A" | "E" 뽑아내야합니다.

 

만약 단순히 type UnionKeys = keyof ExampleValues 이렇게 값을 뽑아내려 하면 "C" 라는 결과만을 얻을 수 있습니다.

 

해당 Union에서 교집합은 "C"이기 때문입니다.

 

모든 Key를 뽑아내기 위해서는 Distributive Conditional Types를 활용하여 다음과 같은 제네릭 타입을 만들어서 사용해주어야 합니다.

NestedKeys Generic Type

 

 

Example의 depth를 늘려보았습니다.

 

위에서 만든 NestedKeys를 조금 수정해보면 다음과 같습니다.

 

AllNestedKeys 제네릭 타입

여기까지는 원하는 대로 잘 나오더군요


 

실패한 부분

타입이 잘 작동하는지 확인하기 위해서 프로퍼티들을 더 추가했습니다.

이 부분은 스택오버플로우의 답변을 가져와서 잘되는 줄 알았는데...

 

참고자료: https://stackoverflow.com/questions/67214581/typescript-get-union-type-of-nested-object-keys

 

TypeScript: Get union type of nested object keys

I wanted to extract types of keys of nested objects and tried something like the below. TS Playground link type RecursiveRecord = { [key in string]: string | RecursiveRecord; }; type Keys<T e...

stackoverflow.com

 

depth를 더 늘리니 객체의 모든 key 값을 다 가져오더군요.

 

더 공부해봐야겠습니다.

failed: AllNestedKeys type