aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-04-19 02:40:46 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-04-19 02:40:46 -0400
commitbe5d2d30bdd98dfc32c28a84ad606eb2b4599932 (patch)
tree179125155c3d09af7eed590bbc2e29267c1be75c /src
parent8eebfed7906e1e2088d528e3af36af21094c38a9 (diff)
Kind of got list typing working for schemas
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/ImageBox.tsx10
-rw-r--r--src/debug/Test.tsx13
-rw-r--r--src/fields/NewDoc.ts43
3 files changed, 49 insertions, 17 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index fe0b07bc0..71b431b84 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -38,7 +38,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
onLoad = (target: any) => {
var h = this._imgRef.current!.naturalHeight;
var w = this._imgRef.current!.naturalWidth;
- if (this._photoIndex == 0) this.props.Document.SetNumber(KeyStore.NativeHeight, this.props.Document.GetNumber(KeyStore.NativeWidth, 0) * h / w);
+ if (this._photoIndex === 0) this.props.Document.SetNumber(KeyStore.NativeHeight, this.props.Document.GetNumber(KeyStore.NativeWidth, 0) * h / w);
}
@@ -53,7 +53,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
onDrop = (e: React.DragEvent) => {
e.stopPropagation();
e.preventDefault();
- console.log("IMPLEMENT ME PLEASE")
+ console.log("IMPLEMENT ME PLEASE");
}
@@ -145,9 +145,9 @@ export class ImageBox extends React.Component<FieldViewProps> {
let left = (nativeWidth - paths.length * dist) / 2;
return paths.map((p, i) =>
<div className="imageBox-placer" key={i} >
- <div className="imageBox-dot" style={{ background: (i == this._photoIndex ? "black" : "gray"), transform: `translate(${i * dist + left}px, 0px)` }} onPointerDown={(e: React.PointerEvent) => { e.stopPropagation(); this.onDotDown(i); }} />
+ <div className="imageBox-dot" style={{ background: (i === this._photoIndex ? "black" : "gray"), transform: `translate(${i * dist + left}px, 0px)` }} onPointerDown={(e: React.PointerEvent) => { e.stopPropagation(); this.onDotDown(i); }} />
</div>
- )
+ );
}
render() {
@@ -159,7 +159,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
let nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 1);
return (
<div className="imageBox-cont" onPointerDown={this.onPointerDown} onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
- <img src={paths[Math.min(paths.length, this._photoIndex)]} style={{ objectFit: (this._photoIndex == 0 ? undefined : "contain") }} width={nativeWidth} alt="Image not found" ref={this._imgRef} onLoad={this.onLoad} />
+ <img src={paths[Math.min(paths.length, this._photoIndex)]} style={{ objectFit: (this._photoIndex === 0 ? undefined : "contain") }} width={nativeWidth} alt="Image not found" ref={this._imgRef} onLoad={this.onLoad} />
{paths.length > 1 ? this.dots(paths) : (null)}
{this.lightbox(paths)}
</div>);
diff --git a/src/debug/Test.tsx b/src/debug/Test.tsx
index b46eb4477..033615be6 100644
--- a/src/debug/Test.tsx
+++ b/src/debug/Test.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { serialize, deserialize, map } from 'serializr';
-import { URLField, Doc, createSchema, makeInterface, makeStrictInterface } from '../fields/NewDoc';
+import { URLField, Doc, createSchema, makeInterface, makeStrictInterface, List, ListSpec } from '../fields/NewDoc';
import { SerializationHelper } from '../client/util/SerializationHelper';
const schema1 = createSchema({
@@ -18,7 +18,7 @@ type TestDoc = makeInterface<typeof schema1>;
const schema2 = createSchema({
hello: URLField,
test: "boolean",
- fields: "string",
+ fields: { List: "number" } as ListSpec<number>,
url: "number",
testDoc: URLField
});
@@ -26,6 +26,13 @@ const schema2 = createSchema({
const Test2Doc = makeStrictInterface(schema2);
type Test2Doc = makeStrictInterface<typeof schema2>;
+const schema3 = createSchema({
+ test: "boolean",
+});
+
+const Test3Doc = makeStrictInterface(schema3);
+type Test3Doc = makeStrictInterface<typeof schema3>;
+
const assert = (bool: boolean) => {
if (!bool) throw new Error();
};
@@ -53,7 +60,7 @@ class Test extends React.Component {
assert(test1.myField === 20);
assert(test2.hello === undefined);
- assert(test2.fields === "test");
+ // assert(test2.fields === "test");
assert(test2.test === undefined);
assert(test2.url === undefined);
assert(test2.testDoc === undefined);
diff --git a/src/fields/NewDoc.ts b/src/fields/NewDoc.ts
index 150b8dae8..7be0d5146 100644
--- a/src/fields/NewDoc.ts
+++ b/src/fields/NewDoc.ts
@@ -107,6 +107,10 @@ export const FieldWaiting: FieldWaiting = null;
const Self = Symbol("Self");
+export class List<T extends Field> extends ObjectField {
+ [index: number]: T;
+}
+
@Deserializable("doc").withFields(["id"])
export class Doc extends RefField {
@@ -230,26 +234,47 @@ export type ToType<T> =
T extends "string" ? string :
T extends "number" ? number :
T extends "boolean" ? boolean :
- T extends { new(...args: any[]): infer R } ? R : undefined;
+ T extends ListSpec<infer U> ? List<U> :
+ T extends { new(...args: any[]): infer R } ? R : never;
+
+export type ToConstructor<T> =
+ T extends string ? "string" :
+ T extends number ? "number" :
+ T extends boolean ? "boolean" : { new(...args: any[]): T };
export type ToInterface<T> = {
[P in keyof T]: ToType<T[P]>;
};
+// type ListSpec<T extends Field[]> = { List: FieldCtor<Head<T>> | ListSpec<Tail<T>> };
+export type ListSpec<T> = { List: FieldCtor<T> };
+
+// type ListType<U extends Field[]> = { 0: List<ListType<Tail<U>>>, 1: ToType<Head<U>> }[HasTail<U> extends true ? 0 : 1];
+
+type Head<T extends any[]> = T extends [any, ...any[]] ? T[0] : never;
+type Tail<T extends any[]> =
+ ((...t: T) => any) extends ((_: any, ...tail: infer TT) => any) ? TT : [];
+type HasTail<T extends any[]> = T extends ([] | [any]) ? false : true;
+
interface Interface {
- [key: string]: { new(...args: any[]): (ObjectField | RefField) } | "number" | "boolean" | "string";
+ [key: string]: ToConstructor<Field> | ListSpec<Field>;
+ // [key: string]: ToConstructor<Field> | ListSpec<Field[]>;
}
-type FieldCtor<T extends Field> = { new(): T } | "number" | "string" | "boolean";
+type FieldCtor<T extends Field> = ToConstructor<T> | ListSpec<Field>;
-function Cast<T extends Field>(field: Field | undefined, ctor: FieldCtor<T>): T | undefined {
+function Cast<T extends Field>(field: Field | undefined, ctor: FieldCtor<T>): ToType<typeof ctor> | undefined {
if (field !== undefined) {
if (typeof ctor === "string") {
if (typeof field === ctor) {
- return field as T;
+ return field as ToType<typeof ctor>;
+ }
+ } else if (typeof ctor === "object") {
+ if (field instanceof List) {
+ return field as ToType<typeof ctor>;
}
- } else if (field instanceof ctor) {
- return field;
+ } else if (field instanceof (ctor as any)) {
+ return field as ToType<typeof ctor>;
}
}
return undefined;
@@ -277,10 +302,10 @@ export function makeStrictInterface<T extends Interface>(schema: T): (doc: Doc)
const type = schema[key];
Object.defineProperty(proto, key, {
get() {
- return Cast(this.__doc[key], type);
+ return Cast(this.__doc[key], type as any);
},
set(value) {
- value = Cast(value, type);
+ value = Cast(value, type as any);
if (value !== undefined) {
this.__doc[key] = value;
return;