Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Infer a tuple type from an array with values of a known type

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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]
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading