Reputation: 633
I want to get the type of a property from a constant previously defined.
const my_constant = {
user: {
props: {
name: {
type: 'string'
}
}
},
media: {
props: {
id: {
type: 'number'
}
}
}
} as const;
type Name = keyof typeof my_constant;
type Constructed<T extends Name> = {
[K in keyof typeof my_constant[T]['props']]: typeof my_constant[T]['props'][K]['type']
// ~~~ Type '"type"' cannot be used to index type ...
}
I don't understand why I cannot use "type" as index but I can use "props".
If typescript can infer that there is always "props" attribute why it cannot infer that there is always "type"?
Is there another way maybe to get the type?
What I want to achieve is something like this:
const user:Constructed<'user'> = {
name: 'John'
}
const media:Constructed<'media'> = {
id: 123
}
const user2:Constructed<'user'> = {
name: 444
// ~~~ Error
}
const media2:Constructed<'media'> = {
id: 'something'
// ~~~ Error
}
Here is the playground link with the exact error:
Upvotes: 3
Views: 3361
Reputation: 551
Typescript cannot use a string to index the constant. It needs the proper key.
You can check if the object has the attribute type
and also maybe use a Mapped type to get the real type instead of just "string".
const my_constant = {
user: {
props: {
name: {
type: 'string'
}
}
},
media: {
props: {
id: {
type: 'number'
}
}
}
} as const;
type Name = keyof typeof my_constant;
type InferType<T> = T extends {type: infer I} ? I : never;
interface Mapped {
string: string;
number: number;
}
type Constructed<T extends Name> = {
[K in keyof typeof my_constant[T]['props']]:
InferType<typeof my_constant[T]['props'][K]> extends keyof Mapped ?
Mapped[InferType<typeof my_constant[T]['props'][K]>] : never
}
Upvotes: 1