sibelius
7/22/2018 - 11:19 PM

types-for-moongose.ts

type TypesDefinition =
  | StringConstructor
  | BooleanConstructor
  | DateConstructor

type FieldDefinition = {
  type: TypesDefinition,
  required?: boolean,
  default?: boolean,
}

type SchemaDefinition = {
  [path: string]: FieldDefinition,
}

type FromTypeDefinition<T extends TypesDefinition> =
  T extends StringConstructor ? string :
  T extends BooleanConstructor ? boolean :
  T extends DateConstructor ? Date :
  never

type OptionalFields<T extends SchemaDefinition> = {
  [K in keyof T]: T[K]['required'] extends boolean ? never : K
}[keyof T]

type RequiredFields<T extends SchemaDefinition> = Exclude<keyof T, OptionalFields<T>>

type ExtractModelDefinition<T extends SchemaDefinition> =
  & { [K in RequiredFields<T>]: FromTypeDefinition<T[K]['type']> }
  & { [K in OptionalFields<T>]?: FromTypeDefinition<T[K]['type']> }

const userSchemaConfig = {
  name: {
    type: String,
    required: true,
  },
  password: {
    type: String,
    hidden: true,
  },
  email: {
    type: String,
    required: false,
    index: true,
  },
  active: {
    type: Boolean,
    default: true,
  },
}

type User = ExtractModelDefinition<typeof userSchemaConfig>
/* =>
{
  name: string,
  email: string,
  password?: string,
  active? boolean,
}
*/