Reputation: 93
for example:
interface a {
name: string
nested: {
lastName: string
nested: {
age: number
}
}
}
I want that to become:
interface b {
name: string
lastName: string
age: number
}
interface values will be dynamic, so I probably need some kind of recursive solution to this
I only ended up with finite solutions
Upvotes: 3
Views: 2950
Reputation: 51044
Here's a solution using mapped and conditional types: FlattenPairs
constructs a union of pairs like ['name', string] | ['lastName', string] | ['age', number]
, then Flatten
converts this into an object type. I assumed that the nested properties are not necessarily all named nested
(and do not necessarily have predictable property names), so the type Primitive
is needed as the base case for the recursion.
type Primitive = string | number | boolean
type FlattenPairs<T> = {[K in keyof T]: T[K] extends Primitive ? [K, T[K]] : FlattenPairs<T[K]>}[keyof T] & [PropertyKey, Primitive]
type Flatten<T> = {[P in FlattenPairs<T> as P[0]]: P[1]}
Example:
interface TestInterface {
name: string
nested: {
lastName: string
nested: {
age: number
}
}
}
// {age: number, lastName: string, name: string}
type Test = Flatten<TestInterface>
The helper type FlattenPairs
can be written in a slightly simpler way if the nested property name(s) are known:
type FlattenPairs<T> = {[K in keyof T]: K extends 'nested' ? FlattenPairs<T[K]> : [K, T[K]]}[keyof T]
Upvotes: 8