aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields
diff options
context:
space:
mode:
Diffstat (limited to 'src/new_fields')
-rw-r--r--src/new_fields/Doc.ts5
-rw-r--r--src/new_fields/HtmlField.ts2
-rw-r--r--src/new_fields/Schema.ts24
-rw-r--r--src/new_fields/Types.ts19
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;
}