So, I'm trying to create an object that can have dynamic attributes, but I want that the IDE can be able to detect the keys that I'm already gave to this object.
if I try this example:
interface Person {
name: string
age: number
}
type dynamicObject = { [key: string]: Person }
const maria: dynamicObject = {
maria: {
name: "Maria",
age: 37
}
}
If I use maria.
to try to detect the keys from the object maria
the IDE will not show me anything.
I know that using generic types I can workaround this problem using [P in keyof T]
interface Person {
name: string
age: number
}
interface Panel<T> {
label: string
fields: (keyof T)[]
}
interface Field<T> {
label: string
value: T
}
interface Form<T> {
panels: { [key : string] : Panel<T> }
fields: { [P in keyof T]?: Field<T[P]> }
}
const form: Form<Person> = {
panels: {
main: {
label: "Panel",
fields: ["name", "age"]
}
},
fields: {
name: {
label: "Name",
value: "Test"
}
}
}
form.panels // not detecting panel keys
form.fields // detecting fields keys
In the example above I'm able to detect the keys from form.fields
because I'm using a type with pre-defined keys. But my goal is to be able to transform this Form type into the same thing but with the possibility of detecting the keys from the form.fields
So, there is any function, remap type, or way to transform this index signature into string literals to accomplish this?
I know that this is possible because there are libraries like stiches.io where you create an object with custom variants and the function generates a new object with the custom keys being detectable by the IDE. I tried to see the magic behind that but the typing is over complicated to understand.
CodePudding user response:
You can't do it with only a type, there needs to be a function with an infered return type (that's what stitches is also doing).
export type Form = { <T>(values?: U): U }
declare const buildForm: Form;
const form = buildForm({
panels: {
main: {
label: "Panel",
fields: ["name", "age"]
}
},
fields: {
name: {
label: "Name",
value: "Test"
}
}
})
form.panels // OK
form.fields // OK