I have some objects that I store content for some UI. They look like this:
const copy = {
header: {
content: 'Page Header'
},
main: {
header: {
content: 'content sub header'
}
body: {
content: 'lorem ipsum....'
}
}
}
I have written a proxy which lets me get an ID, generated by the deeply nested path of the content I am accessing:
const isObject = (obj: unknown): obj is Record<string, any> =>
typeof obj === 'object' && obj != null
const createHander = <T extends Record<string, any>>(path: string[]) => ({
get: (target: T, key: string): any => {
if (key === 'id') {
return path.join('-')
}
const newTarget = target[key]
if (isObject(newTarget)) {
return new Proxy(newTarget, createHander([...path, key]))
}
return newTarget
},
})
export const withIds = (copyObject: Record<string, any>, initialId: string) =>
new Proxy(copyObject, createHander([initialId]))
so the following is true:
const copyWithIds = withIds(copy, 'page')
copyWithIds.main.body.id // page-main-body
Trouble is, everything on the copyWithId's object is now of type any
I would like to not be reliant on the any
type as the return of the get
but struggling to find a set up that works
CodePudding user response:
You can use a mapped type to emulate what you are doing in the function code
type WithId<T> = {
[P in keyof T]: T[P] extends object ? WithId<T[P]> : never
} & {
id: string
}
export const withIds = <T extends Record<string, any>>(copyObject: T, initialId: string) =>
new Proxy(copyObject, createHander([initialId])) as unknown as WithId<T>