diff options
Diffstat (limited to 'src/new_fields')
-rw-r--r-- | src/new_fields/Doc.ts | 5 | ||||
-rw-r--r-- | src/new_fields/HtmlField.ts | 2 | ||||
-rw-r--r-- | src/new_fields/Schema.ts | 24 | ||||
-rw-r--r-- | src/new_fields/Types.ts | 19 |
4 files changed, 37 insertions, 13 deletions
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 23a8c05cc..e0eb44ee9 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -33,6 +33,7 @@ export type Field = number | string | boolean | ObjectField | RefField; export type Opt<T> = T | undefined; export type FieldWaiting = null; export const FieldWaiting: FieldWaiting = null; +export type FieldValue<T extends Field = Field> = Opt<T> | FieldWaiting; export const Self = Symbol("Self"); @@ -81,8 +82,8 @@ export namespace Doc { const self = doc[Self]; return getField(self, key, ignoreProto); } - export function GetT<T extends Field>(doc: Doc, key: string, ctor: FieldCtor<T>, ignoreProto: boolean = false): Field | null | undefined { - return Cast(Get(doc, key, ignoreProto), ctor); + export function GetT<T extends Field>(doc: Doc, key: string, ctor: FieldCtor<T>, ignoreProto: boolean = false): T | null | undefined { + return Cast(Get(doc, key, ignoreProto), ctor) as T | null | undefined; } export function MakeDelegate(doc: Opt<Doc>): Opt<Doc> { if (!doc) { diff --git a/src/new_fields/HtmlField.ts b/src/new_fields/HtmlField.ts index f8e54ade5..76fdb1f62 100644 --- a/src/new_fields/HtmlField.ts +++ b/src/new_fields/HtmlField.ts @@ -3,7 +3,7 @@ import { serializable, primitive } from "serializr"; import { ObjectField } from "./Doc"; @Deserializable("html") -export class URLField extends ObjectField { +export class HtmlField extends ObjectField { @serializable(primitive()) readonly html: string; diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts index 1607d4c15..1d1f56844 100644 --- a/src/new_fields/Schema.ts +++ b/src/new_fields/Schema.ts @@ -1,8 +1,26 @@ -import { Interface, ToInterface, Cast, FieldCtor, ToConstructor } from "./Types"; +import { Interface, ToInterface, Cast, FieldCtor, ToConstructor, HasTail, Head, Tail } from "./Types"; import { Doc } from "./Doc"; -export type makeInterface<T extends Interface, U extends Doc = Doc> = Partial<ToInterface<T>> & U; -export function makeInterface<T extends Interface, U extends Doc>(schema: T): (doc: U) => makeInterface<T, U> { +type All<T extends any[], U extends Doc> = { + 1: makeInterface<Head<T>, U> & All<Tail<T>, U>, + 0: makeInterface<Head<T>, U> +}[HasTail<T> extends true ? 1 : 0]; + +type AllToInterface<T extends any[]> = { + 1: ToInterface<Head<T>> & AllToInterface<Tail<T>>, + 0: ToInterface<Head<T>> +}[HasTail<T> extends true ? 1 : 0]; + +export type makeInterface<T extends Interface[], U extends Doc = Doc> = Partial<AllToInterface<T>> & U; +// export function makeInterface<T extends Interface[], U extends Doc>(schemas: T): (doc: U) => All<T, U>; +// export function makeInterface<T extends Interface, U extends Doc>(schema: T): (doc: U) => makeInterface<T, U>; +export function makeInterface<T extends Interface[], U extends Doc>(schemas: T): (doc: U) => All<T, U> { + let schema: Interface = {}; + for (const s of schemas) { + for (const key in s) { + schema[key] = s[key]; + } + } return function (doc: any) { return new Proxy(doc, { get(target, prop) { diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index cafb208ce..6ffb3e02f 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -27,14 +27,17 @@ export type Tail<T extends any[]> = ((...t: T) => any) extends ((_: any, ...tail: infer TT) => any) ? TT : []; export type HasTail<T extends any[]> = T extends ([] | [any]) ? false : true; +//TODO Allow you to optionally specify default values for schemas, which should then make that field not be partial export interface Interface { [key: string]: ToConstructor<Field> | ListSpec<Field>; // [key: string]: ToConstructor<Field> | ListSpec<Field[]>; } -export type FieldCtor<T extends Field> = ToConstructor<T> | ListSpec<T>; +export type FieldCtor<T extends Field> = T extends List<infer R> ? ListSpec<R> : ToConstructor<T>; -export function Cast<T extends FieldCtor<Field>>(field: Field | null | undefined, ctor: T): ToType<T> | null | undefined { +export function Cast<T extends FieldCtor<Field>>(field: Field | null | undefined, ctor: T): ToType<T> | null | undefined; +export function Cast<T extends FieldCtor<Field>>(field: Field | null | undefined, ctor: T, defaultVal: ToType<T>): ToType<T>; +export function Cast<T extends FieldCtor<Field>>(field: Field | null | undefined, ctor: T, defaultVal?: ToType<T>): ToType<T> | null | undefined { if (field !== undefined && field !== null) { if (typeof ctor === "string") { if (typeof field === ctor) { @@ -42,17 +45,19 @@ export function Cast<T extends FieldCtor<Field>>(field: Field | null | undefined } } else if (typeof ctor === "object") { if (field instanceof List) { - return field as ToType<T>; + return field as any; } } else if (field instanceof (ctor as any)) { return field as ToType<T>; } } else { - return field; + return defaultVal; } - return undefined; + return defaultVal; } -export function FieldValue<T extends Field>(field: Opt<T> | Promise<Opt<T>>): Opt<T> { - return field instanceof Promise ? undefined : field; +export function FieldValue<T extends Field, U extends T>(field: Opt<T> | Promise<Opt<T>>, defaultValue: U): T; +export function FieldValue<T extends Field>(field: Opt<T> | Promise<Opt<T>>): Opt<T>; +export function FieldValue<T extends Field>(field: Opt<T> | Promise<Opt<T>>, defaultValue?: T): Opt<T> { + return field instanceof Promise ? defaultValue : field; } |