export type NonPromise = undefined|{ then? : undefined }; export type DefaultType = F | { () : F & NonPromise }; export type CheckFunction = ((name : string, mixed : any) => Promise); export type CheckType = CheckFunction | Schema | { () : F & NonPromise }; //Workaround for Date being both { () : string } and { new() : Date } export const DateInstance = () : Date => { //new Date() is the same as new Date(Date.now()) //But the latter is more explicit return new Date(Date.now()); }; //Arrays export const StringArray = () : string[] => { return []; }; export const NumberArray = () : number[] => { return []; }; export const BooleanArray = () : boolean[] => { return []; }; export const DateArray = () : Date[] => { return []; }; //Optionals export const OptionalString = () : undefined|string => { return undefined; }; export const OptionalNumber = () : undefined|number => { return undefined; }; export const OptionalBoolean = () : undefined|boolean => { return undefined; }; export const OptionalDate = () : undefined|Date => { return undefined; }; export type CheckObject = { default: DefaultType, check : CheckType }; export type Field = CheckType | CheckObject; export type Fields = { [fieldName in keyof T] : Field }; /* The idea is to just define default values and checks. If no default is given for a field, no default value exists. If no check is given for a field, a simple data-type check is done. `check` should only really be defined for more complicated data types like integers only, positive numbers only, nested objects, etc. */ export interface Schema { //If enabled, the object may have additional fields whose values will not be checked allowExtraFields? : boolean; check?: (name : string, target : T) => Promise, fields: Fields, }