-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: recursive ToJSON #174
base: master
Are you sure you want to change the base?
Changes from 3 commits
caa651b
58b014b
160428e
9af6637
0591a6d
f208847
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ import { CollectionSchema } from './types/CollectionSchema'; | |
import { SetSchema } from './types/SetSchema'; | ||
|
||
import { ChangeTree, Ref, ChangeOperation } from "./changes/ChangeTree"; | ||
import { NonFunctionPropNames, ToJSON } from './types/HelperTypes'; | ||
import { NonFunctionPropNames, NonFunctionProps, ToJSON } from './types/HelperTypes'; | ||
import { ClientState } from './filters'; | ||
import { getType } from './types/typeRegistry'; | ||
import { ReferenceTracker } from './changes/ReferenceTracker'; | ||
|
@@ -894,7 +894,9 @@ export abstract class Schema { | |
return cloned; | ||
} | ||
|
||
toJSON () { | ||
toJSON (): NonFunctionProps<{ | ||
[field in keyof this]: ToJSON<this[field]> | ||
}> { | ||
const schema = this._definition.schema; | ||
const deprecated = this._definition.deprecated; | ||
|
||
|
@@ -906,7 +908,9 @@ export abstract class Schema { | |
: this[`_${field}`]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand this part: why is there an underscore? |
||
} | ||
} | ||
return obj as ToJSON<typeof this>; | ||
return obj as NonFunctionProps<{ | ||
[field in keyof this]: ToJSON<this[field]> | ||
}> | ||
} | ||
|
||
discardAllChanges() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// Used to check if two types are equal. | ||
// If they are equal, the expression evaluates to true, otherwise false | ||
export type Equals<T1, T2> = T1 extends T2 | ||
? T2 extends T1 | ||
? true | ||
: false | ||
: false |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
import { ArraySchema, CollectionSchema, MapSchema, Schema, SetSchema, ToJSON, type } from "../../src"; | ||
import { Equals } from "../helpers/Equals"; | ||
|
||
// Reused across multiple tests | ||
export class VecSchema extends Schema { | ||
@type('number') x: number | ||
@type('number') y: number | ||
} | ||
|
||
describe("ToJSON type tests", () => { | ||
it("Omits methods", () => { | ||
class C extends Schema { | ||
@type('number') time: number | ||
rewind(arg: number){} | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
time: number | ||
}> = true | ||
}) | ||
|
||
it("Does not transform primitive types", () => { | ||
// Primitive types have methods, and these should not be omitted | ||
const _tString: Equals<ToJSON<string>, string> = true | ||
const _tNumber: Equals<ToJSON<number>, number> = true | ||
const _tBoolean: Equals<ToJSON<boolean>, boolean> = true | ||
const _tBigInt: Equals<ToJSON<bigint>, bigint> = true | ||
const _tSymbol: Equals<ToJSON<symbol>, symbol> = true | ||
const _tUndefined: Equals<ToJSON<undefined>, undefined> = true | ||
const _tNull: Equals<ToJSON<null>, null> = true | ||
}) | ||
|
||
it("Does not transform non-schema types", () => { | ||
class C extends Schema { | ||
time: number | ||
pos: { x: number, y: number } | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
time: number | ||
pos: { x: number, y: number } | ||
}> = true | ||
const _t2: ToJSON<C> = { | ||
time: 1, | ||
pos: { x: 1, y: 2 } | ||
} | ||
}) | ||
|
||
it("Primitive type on root", () => { | ||
class C extends Schema { | ||
@type('number') time: number | ||
@type('string') name: string | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
time: number | ||
name: string | ||
}> = true | ||
const _t2: ToJSON<C> = { | ||
time: 1, | ||
name: "name" | ||
} | ||
}) | ||
|
||
it("Schema type on root", () => { | ||
class C extends Schema { | ||
@type(VecSchema) ballPos: VecSchema | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
ballPos: { | ||
x: number | ||
y: number | ||
} | ||
}> = true | ||
const _t2: ToJSON<C> = { | ||
ballPos: { | ||
x: 1, | ||
y: 2 | ||
} | ||
} | ||
}) | ||
|
||
it("Map on root", () => { | ||
class C extends Schema { | ||
@type({map: VecSchema}) positions: MapSchema<VecSchema> | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
positions: Record<string, { | ||
x: number | ||
y: number | ||
}> | ||
}> = true | ||
const _t2: ToJSON<C> = { | ||
positions: { | ||
a: { | ||
x: 1, | ||
y: 2 | ||
} | ||
} | ||
} | ||
}) | ||
|
||
it("MapSchema on root", () => { | ||
class C extends Schema { | ||
@type({map: VecSchema}) positions: MapSchema<VecSchema> | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
positions: Record<string, { | ||
x: number | ||
y: number | ||
}> | ||
}> = true | ||
const _t2: ToJSON<C> = { | ||
positions: { | ||
a: { | ||
x: 1, | ||
y: 2 | ||
} | ||
} | ||
} | ||
}) | ||
|
||
it("ArraySchema on root", () => { | ||
class C extends Schema { | ||
@type({map: VecSchema}) positions: ArraySchema<VecSchema> | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
positions: Array<{ | ||
x: number | ||
y: number | ||
}> | ||
}> = true | ||
const _t2: ToJSON<C> = { | ||
positions: [{ | ||
x: 1, | ||
y: 2 | ||
}] | ||
} | ||
}) | ||
|
||
it("SetSchema on root", () => { | ||
class C extends Schema { | ||
@type({map: VecSchema}) positions: SetSchema<VecSchema> | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
positions: Array<{ | ||
x: number | ||
y: number | ||
}> | ||
}> = true | ||
const _t2: ToJSON<C> = { | ||
positions: [{ | ||
x: 1, | ||
y: 2 | ||
}] | ||
} | ||
}) | ||
|
||
it("CollectionSchema on root", () => { | ||
class C extends Schema { | ||
@type({map: VecSchema}) positions: CollectionSchema<VecSchema> | ||
} | ||
const _t1: Equals<ToJSON<C>, { | ||
positions: Array<{ | ||
x: number | ||
y: number | ||
}> | ||
}> = true | ||
const _t2: ToJSON<C> = { | ||
positions: [{ | ||
x: 1, | ||
y: 2 | ||
}] | ||
} | ||
}) | ||
}) |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line 41 tests some types, but these types are never checked unless this file is moved into a subdirectory to the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect this type is not entirely accurate, because there is a conditional that seems to omit
null
values. This hasn't been taken into account, but this isn't being taken into account in the current implementation anyways.