Why does typescript infer Array in this conditional type?

84 Views Asked by At

I have the following conditional type:

type ComplexType<T> = {
  [key in keyof T]: T[key] extends {
    type: unknown
    schema?: unknown
  }
    ?
        | (T[key]['schema'] extends object
            ? ComplexType<T[key]['schema']>
            : never)
        | TypeFromConstructor<T[key]['type']>
    : TypeFromConstructor<T[key]> | undefined
}

type TypeFromConstructor<T> = T extends StringConstructor
  ? string
  : T extends NumberConstructor
  ? number
  : T extends BooleanConstructor
  ? boolean
  : T extends DateConstructor
  ? Date
  : T extends ArrayConstructor
  ? never
  : T extends ObjectConstructor
  ? never
  : unknown

If I now use it on an object like this:

const schema = {
  test: {
    type: Array,
    schema: [{
      type: Object,
      schema: {
        id: String,
      },
    }],
  },
}
type testType = ComplexType<typeof schema>

testType yields smth like: { test: Array<{id: string}> }, but I would have expected smth like { test: { '0': {id: string}} } because I never check if the type of schema is an array. I understand that iterating over the keys will also iterate over the array elements, but how can it infer it being an array, when the type does not check for it? And why does it not include the default array properties like length, etc into the type? Does it have smth to do with that an array is just an object in javascript?

0

There are 0 best solutions below