I am trying to write code that achieves the following:
Imagine I have code elsewhere that defines class Schema<T extends string|number|boolean>,
Now let’s say I write
const superSchema = [
new Schema<string>(),
new Schema<number>(),
new Schema<boolean>(),
new Schema<number>()
]
I want to define a type called SuperSchemaInfer such that SuperSchemaInfer<typeof superSchema> is equal to [string, number, boolean, number].
How can I do this? I think it should be possible since Zod does something similar.
So far I have written some code, but all I was able to get was SuperSchemaInfer<typeof superSchema> equal to (string|number|boolean)[].
Here is my code so far:
type SupportedTypes = string | number | boolean
type SchemaArray = Array<Schema<SupportedTypes>>
type SchemaArrayInfer<S extends SchemaArray> = {
[K in keyof S]: S[K] extends Schema<infer U> ? U : never
}
>Solution :
Your problem is not with the type you wrote, but with the type you input
const superSchema = [
// ^?
// const superSchema: (Schema<string> | Schema<number> | Schema<boolean>)[]
new Schema<string>(),
new Schema<number>(),
new Schema<boolean>(),
new Schema<number>()
]
All you need to fix this is to mark array as const and change generic to support ReadonlyArray
type SchemaArrayInfer<S extends readonly Schema<string | number | boolean>[]> = {
[K in keyof S]: S[K] extends Schema<infer U> ? U : never
}
const superSchema = [
// ^?
// const superSchema: (Schema<string> | Schema<number> | Schema<boolean>)[]
new Schema<string>(),
new Schema<number>(),
new Schema<boolean>(),
new Schema<number>()
] as const
type R = SchemaArrayInfer<typeof superSchema>
// ^?
// type R = readonly [string, number, boolean, number]