aboutsummaryrefslogtreecommitdiff
path: root/src/fields/Types.ts
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-04-05 22:44:03 -0400
committerbobzel <zzzman@gmail.com>2023-04-05 22:44:03 -0400
commit9b41da1af16b982ee8ac2fc09f2f8b5d67eac9fb (patch)
treebc3f57cd5b31fd453d272c925f6d5b728ab63bae /src/fields/Types.ts
parent9dae453967183b294bf4f7444b948023a1d52d39 (diff)
parent8f7e99641f84ad15f34ba9e4a60b664ac93d2e5d (diff)
Merge branch 'master' into data-visualization-view-naafi
Diffstat (limited to 'src/fields/Types.ts')
-rw-r--r--src/fields/Types.ts93
1 files changed, 50 insertions, 43 deletions
diff --git a/src/fields/Types.ts b/src/fields/Types.ts
index bf40a0d7b..4cf286a32 100644
--- a/src/fields/Types.ts
+++ b/src/fields/Types.ts
@@ -1,48 +1,50 @@
-import { Field, Opt, FieldResult, Doc } from "./Doc";
-import { List } from "./List";
-import { RefField } from "./RefField";
-import { DateField } from "./DateField";
-import { ScriptField } from "./ScriptField";
-import { URLField, WebField, ImageField } from "./URLField";
-import { TextField } from "@material-ui/core";
-import { RichTextField } from "./RichTextField";
-
-export type ToType<T extends InterfaceValue> =
- T extends "string" ? string :
- T extends "number" ? number :
- T extends "boolean" ? boolean :
- T extends ListSpec<infer U> ? List<U> :
- // T extends { new(...args: any[]): infer R } ? (R | Promise<R>) : never;
- T extends DefaultFieldConstructor<infer _U> ? never :
- T extends { new(...args: any[]): List<Field> } ? never :
- T extends { new(...args: any[]): infer R } ? R :
- T extends (doc?: Doc) => infer R ? R : never;
-
-export type ToConstructor<T extends Field> =
- T extends string ? "string" :
- T extends number ? "number" :
- T extends boolean ? "boolean" :
- T extends List<infer U> ? ListSpec<U> :
- new (...args: any[]) => T;
+import { Field, Opt, FieldResult, Doc } from './Doc';
+import { List } from './List';
+import { RefField } from './RefField';
+import { DateField } from './DateField';
+import { ScriptField } from './ScriptField';
+import { URLField, WebField, ImageField } from './URLField';
+import { TextField } from '@material-ui/core';
+import { RichTextField } from './RichTextField';
+
+export type ToType<T extends InterfaceValue> = T extends 'string'
+ ? string
+ : T extends 'number'
+ ? number
+ : T extends 'boolean'
+ ? boolean
+ : T extends ListSpec<infer U>
+ ? List<U>
+ : // T extends { new(...args: any[]): infer R } ? (R | Promise<R>) : never;
+ T extends DefaultFieldConstructor<infer _U>
+ ? never
+ : T extends { new (...args: any[]): List<Field> }
+ ? never
+ : T extends { new (...args: any[]): infer R }
+ ? R
+ : T extends (doc?: Doc) => infer R
+ ? R
+ : never;
+
+export type ToConstructor<T extends Field> = T extends string ? 'string' : T extends number ? 'number' : T extends boolean ? 'boolean' : T extends List<infer U> ? ListSpec<U> : new (...args: any[]) => T;
export type ToInterface<T extends Interface> = {
- [P in Exclude<keyof T, "proto">]: T[P] extends DefaultFieldConstructor<infer F> ? Exclude<FieldResult<F>, undefined> : FieldResult<ToType<T[P]>>;
+ [P in Exclude<keyof T, 'proto'>]: T[P] extends DefaultFieldConstructor<infer F> ? Exclude<FieldResult<F>, undefined> : FieldResult<ToType<T[P]>>;
};
// type ListSpec<T extends Field[]> = { List: ToContructor<Head<T>> | ListSpec<Tail<T>> };
export type ListSpec<T extends Field> = { List: ToConstructor<T> };
export type DefaultFieldConstructor<T extends Field> = {
- type: ToConstructor<T>,
- defaultVal: T
+ type: ToConstructor<T>;
+ defaultVal: T;
};
// type ListType<U extends Field[]> = { 0: List<ListType<Tail<U>>>, 1: ToType<Head<U>> }[HasTail<U> extends true ? 0 : 1];
export type Head<T extends any[]> = T extends [any, ...any[]] ? T[0] : never;
-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;
+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;
export type InterfaceValue = ToConstructor<Field> | ListSpec<Field> | DefaultFieldConstructor<Field> | ((doc?: Doc) => any);
//TODO Allow you to optionally specify default values for schemas, which should then make that field not be partial
@@ -58,14 +60,14 @@ export function Cast<T extends CastCtor>(field: FieldResult, ctor: T): FieldResu
export function Cast<T extends CastCtor>(field: FieldResult, ctor: T, defaultVal: WithoutList<WithoutRefField<ToType<T>>> | null): WithoutList<ToType<T>>;
export function Cast<T extends CastCtor>(field: FieldResult, ctor: T, defaultVal?: ToType<T> | null): FieldResult<ToType<T>> | undefined {
if (field instanceof Promise) {
- return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) as any : defaultVal === null ? undefined : defaultVal;
+ return defaultVal === undefined ? (field.then(f => Cast(f, ctor) as any) as any) : defaultVal === null ? undefined : defaultVal;
}
if (field !== undefined && !(field instanceof Promise)) {
- if (typeof ctor === "string") {
+ if (typeof ctor === 'string') {
if (typeof field === ctor) {
return field as ToType<T>;
}
- } else if (typeof ctor === "object") {
+ } else if (typeof ctor === 'object') {
if (field instanceof List) {
return field as any;
}
@@ -77,19 +79,20 @@ export function Cast<T extends CastCtor>(field: FieldResult, ctor: T, defaultVal
}
export function DocCast(field: FieldResult, defaultVal?: Doc) {
- return Cast(field, Doc, null) ?? defaultVal;
+ const doc = Cast(field, Doc, null);
+ return doc && !(doc instanceof Promise) ? doc : (defaultVal as Doc);
}
export function NumCast(field: FieldResult, defaultVal: number | null = 0) {
- return Cast(field, "number", defaultVal);
+ return Cast(field, 'number', defaultVal);
}
-export function StrCast(field: FieldResult, defaultVal: string | null = "") {
- return Cast(field, "string", defaultVal);
+export function StrCast(field: FieldResult, defaultVal: string | null = '') {
+ return Cast(field, 'string', defaultVal);
}
export function BoolCast(field: FieldResult, defaultVal: boolean | null = false) {
- return Cast(field, "boolean", defaultVal);
+ return Cast(field, 'boolean', defaultVal);
}
export function DateCast(field: FieldResult) {
return Cast(field, DateField, null);
@@ -113,7 +116,7 @@ type WithoutList<T extends Field> = T extends List<infer R> ? (R extends RefFiel
export function FieldValue<T extends Field, U extends WithoutList<T>>(field: FieldResult<T>, defaultValue: U): WithoutList<T>;
export function FieldValue<T extends Field>(field: FieldResult<T>): Opt<T>;
export function FieldValue<T extends Field>(field: FieldResult<T>, defaultValue?: T): Opt<T> {
- return (field instanceof Promise || field === undefined) ? defaultValue : field;
+ return field instanceof Promise || field === undefined ? defaultValue : field;
}
export interface PromiseLike<T> {
@@ -121,5 +124,9 @@ export interface PromiseLike<T> {
}
export function PromiseValue<T extends Field>(field: FieldResult<T>): PromiseLike<Opt<T>> {
if (field instanceof Promise) return field as Promise<Opt<T>>;
- return { then(cb: ((field: Opt<T>) => void)) { return cb(field); } };
-} \ No newline at end of file
+ return {
+ then(cb: (field: Opt<T>) => void) {
+ return cb(field);
+ },
+ };
+}