inferred-types 0.15.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.tsbuildinfo +1 -0
- package/devops/build.js +1 -3
- package/dist/{types/utility/state/KeyStorage.d.ts → index.d.ts} +9767 -8195
- package/dist/index.js +659 -0
- package/dist/index.mjs +577 -0
- package/on-hold/tests/api-spec.ts +9 -15
- package/package.json +27 -37
- package/pnpm-lock.yaml +2385 -2117
- package/src/errors/InferenceError.ts +1 -1
- package/src/shared/randomString.ts +1 -1
- package/src/types/Constructor.ts +5 -0
- package/src/types/Not.ts +3 -1
- package/src/types/Transformer.ts +1 -2
- package/src/types/Where.ts +36 -0
- package/src/types/alphabetic/PascalCase.ts +5 -4
- package/src/types/alphabetic/index.ts +9 -5
- package/src/types/{fluent.ts → fluent/fluent.ts} +8 -9
- package/src/types/fluent/index.ts +42 -0
- package/src/types/index.ts +13 -7
- package/src/types/lists/UniqueForProp.ts +13 -3
- package/src/types/ruleset-types.ts +1 -1
- package/src/types/{SameKeys.ts → type-conversion/SameKeys.ts} +0 -0
- package/src/types/type-conversion/WrapValue.ts +15 -0
- package/src/types/type-conversion/index.ts +11 -4
- package/src/utility/dictionary/arrayToKeyLookup.ts +3 -4
- package/src/utility/dictionary/dictionaryTransform.ts +6 -7
- package/src/utility/index.ts +3 -2
- package/src/utility/lists/groupBy.ts +22 -0
- package/src/utility/lists/index.ts +38 -0
- package/tests/Where.spec.ts +39 -0
- package/tests/constructor.spec.ts +40 -0
- package/tests/data/index.ts +8 -3
- package/tests/kv/dict-to-kv-and-back.spec.ts +2 -6
- package/tsconfig.json +4 -3
- package/dist/cjs/index.js +0 -21
- package/dist/es/index.js +0 -17
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/types/Mutation/MutationFunction.d.ts +0 -16
- package/dist/types/Mutation/MutationIdentity.d.ts +0 -30
- package/dist/types/Mutation/index.d.ts +0 -2
- package/dist/types/errors/InferenceError.d.ts +0 -1
- package/dist/types/errors/index.d.ts +0 -1
- package/dist/types/index.d.ts +0 -4
- package/dist/types/shared/index.d.ts +0 -3
- package/dist/types/shared/randomString.d.ts +0 -1
- package/dist/types/shared/uuid.d.ts +0 -1
- package/dist/types/shared/valueTypes.d.ts +0 -27
- package/dist/types/types/Api.d.ts +0 -10
- package/dist/types/types/EnumValues.d.ts +0 -14
- package/dist/types/types/ExpandRecursively.d.ts +0 -3
- package/dist/types/types/First.d.ts +0 -4
- package/dist/types/types/FunctionType.d.ts +0 -9
- package/dist/types/types/If.d.ts +0 -10
- package/dist/types/types/Include.d.ts +0 -16
- package/dist/types/types/Includes.d.ts +0 -5
- package/dist/types/types/KeyedRecord.d.ts +0 -22
- package/dist/types/types/Keys.d.ts +0 -17
- package/dist/types/types/Length.d.ts +0 -8
- package/dist/types/types/Mutable.d.ts +0 -6
- package/dist/types/types/Narrowable.d.ts +0 -5
- package/dist/types/types/Not.d.ts +0 -11
- package/dist/types/types/Numeric.d.ts +0 -14
- package/dist/types/types/Opaque.d.ts +0 -12
- package/dist/types/types/Retain.d.ts +0 -16
- package/dist/types/types/SameKeys.d.ts +0 -11
- package/dist/types/types/Transformer.d.ts +0 -11
- package/dist/types/types/TypeGuard.d.ts +0 -7
- package/dist/types/types/alphabetic/AllCaps.d.ts +0 -12
- package/dist/types/types/alphabetic/CamelCase.d.ts +0 -2
- package/dist/types/types/alphabetic/CapFirstAlpha.d.ts +0 -13
- package/dist/types/types/alphabetic/CapitalizeWords.d.ts +0 -4
- package/dist/types/types/alphabetic/DashToSnake.d.ts +0 -1
- package/dist/types/types/alphabetic/DashUppercase.d.ts +0 -14
- package/dist/types/types/alphabetic/Dasherize.d.ts +0 -15
- package/dist/types/types/alphabetic/HasUppercase.d.ts +0 -13
- package/dist/types/types/alphabetic/Intrinsic.d.ts +0 -4
- package/dist/types/types/alphabetic/IsCapitalized.d.ts +0 -15
- package/dist/types/types/alphabetic/KebabCase.d.ts +0 -12
- package/dist/types/types/alphabetic/LowerAllCaps.d.ts +0 -4
- package/dist/types/types/alphabetic/PascalCase.d.ts +0 -16
- package/dist/types/types/alphabetic/Pluralize.d.ts +0 -36
- package/dist/types/types/alphabetic/SnakeCase.d.ts +0 -14
- package/dist/types/types/alphabetic/alpha-characters.d.ts +0 -36
- package/dist/types/types/alphabetic/index.d.ts +0 -16
- package/dist/types/types/append-types.d.ts +0 -9
- package/dist/types/types/dictionary/Get.d.ts +0 -7
- package/dist/types/types/dictionary/index.d.ts +0 -1
- package/dist/types/types/fluent.d.ts +0 -51
- package/dist/types/types/index.d.ts +0 -34
- package/dist/types/types/kv/DictFromKv.d.ts +0 -6
- package/dist/types/types/kv/KeyValue.d.ts +0 -11
- package/dist/types/types/kv/KvFrom.d.ts +0 -13
- package/dist/types/types/kv/KvTuple.d.ts +0 -14
- package/dist/types/types/kv/index.d.ts +0 -4
- package/dist/types/types/lists/UniqueForProp.d.ts +0 -5
- package/dist/types/types/lists/index.d.ts +0 -1
- package/dist/types/types/maybe.d.ts +0 -8
- package/dist/types/types/props.d.ts +0 -100
- package/dist/types/types/ruleset-types.d.ts +0 -59
- package/dist/types/types/runtime.d.ts +0 -33
- package/dist/types/types/string-literals/Break.d.ts +0 -12
- package/dist/types/types/string-literals/Concat.d.ts +0 -8
- package/dist/types/types/string-literals/LeftWhitespace.d.ts +0 -9
- package/dist/types/types/string-literals/Replace.d.ts +0 -11
- package/dist/types/types/string-literals/RightWhitespace.d.ts +0 -9
- package/dist/types/types/string-literals/StringLength.d.ts +0 -10
- package/dist/types/types/string-literals/Trim.d.ts +0 -11
- package/dist/types/types/string-literals/TrimLeft.d.ts +0 -11
- package/dist/types/types/string-literals/TrimRight.d.ts +0 -11
- package/dist/types/types/string-literals/form-fields.d.ts +0 -12
- package/dist/types/types/string-literals/index.d.ts +0 -10
- package/dist/types/types/tuples/DictArray.d.ts +0 -19
- package/dist/types/types/tuples/FirstKey.d.ts +0 -8
- package/dist/types/types/tuples/FirstKeyValue.d.ts +0 -8
- package/dist/types/types/tuples/FirstOfEach.d.ts +0 -11
- package/dist/types/types/tuples/FromDictArray.d.ts +0 -10
- package/dist/types/types/tuples/SecondOfEach.d.ts +0 -10
- package/dist/types/types/tuples/index.d.ts +0 -6
- package/dist/types/types/type-conversion/TupleToUnion.d.ts +0 -10
- package/dist/types/types/type-conversion/UnionToIntersection.d.ts +0 -5
- package/dist/types/types/type-conversion/UnionToTuple.d.ts +0 -9
- package/dist/types/types/type-conversion/index.d.ts +0 -3
- package/dist/types/types/type-testing.d.ts +0 -13
- package/dist/types/utility/api/api.d.ts +0 -2
- package/dist/types/utility/api/index.d.ts +0 -1
- package/dist/types/utility/createFnWithProps.d.ts +0 -1
- package/dist/types/utility/dictionary/arrayToKeyLookup.d.ts +0 -10
- package/dist/types/utility/dictionary/dictFilter.d.ts +0 -8
- package/dist/types/utility/dictionary/dictionaryTransform.d.ts +0 -9
- package/dist/types/utility/dictionary/entries.d.ts +0 -17
- package/dist/types/utility/dictionary/index.d.ts +0 -8
- package/dist/types/utility/dictionary/kv/dictToKv.d.ts +0 -16
- package/dist/types/utility/dictionary/kv/filterDictArray.d.ts +0 -9
- package/dist/types/utility/dictionary/kv/index.d.ts +0 -4
- package/dist/types/utility/dictionary/kv/kv.d.ts +0 -10
- package/dist/types/utility/dictionary/kv/kvToDict.d.ts +0 -15
- package/dist/types/utility/dictionary/mapValues.d.ts +0 -13
- package/dist/types/utility/dictionary/strArrayToDict.d.ts +0 -6
- package/dist/types/utility/dictionary/valuesOfProp.d.ts +0 -1
- package/dist/types/utility/index.d.ts +0 -10
- package/dist/types/utility/keys.d.ts +0 -5
- package/dist/types/utility/literals/ExplicitFunction.d.ts +0 -6
- package/dist/types/utility/literals/arrayToObject.d.ts +0 -41
- package/dist/types/utility/literals/defineType.d.ts +0 -8
- package/dist/types/utility/literals/identity.d.ts +0 -6
- package/dist/types/utility/literals/index.d.ts +0 -5
- package/dist/types/utility/literals/literal.d.ts +0 -41
- package/dist/types/utility/map-reduce/filter.d.ts +0 -26
- package/dist/types/utility/map-reduce/index.d.ts +0 -1
- package/dist/types/utility/modelling/IoModel.d.ts +0 -26
- package/dist/types/utility/modelling/Model.d.ts +0 -22
- package/dist/types/utility/modelling/index.d.ts +0 -1
- package/dist/types/utility/ruleset.d.ts +0 -18
- package/dist/types/utility/runtime/condition.d.ts +0 -3
- package/dist/types/utility/runtime/conditions/index.d.ts +0 -12
- package/dist/types/utility/runtime/conditions/isArray.d.ts +0 -2
- package/dist/types/utility/runtime/conditions/isBoolean.d.ts +0 -5
- package/dist/types/utility/runtime/conditions/isFalse.d.ts +0 -4
- package/dist/types/utility/runtime/conditions/isFunction.d.ts +0 -15
- package/dist/types/utility/runtime/conditions/isLiteral.d.ts +0 -2
- package/dist/types/utility/runtime/conditions/isNull.d.ts +0 -1
- package/dist/types/utility/runtime/conditions/isNumber.d.ts +0 -1
- package/dist/types/utility/runtime/conditions/isObject.d.ts +0 -10
- package/dist/types/utility/runtime/conditions/isString.d.ts +0 -2
- package/dist/types/utility/runtime/conditions/isSymbol.d.ts +0 -1
- package/dist/types/utility/runtime/conditions/isTrue.d.ts +0 -20
- package/dist/types/utility/runtime/conditions/isUndefined.d.ts +0 -1
- package/dist/types/utility/runtime/ifTypeOf.d.ts +0 -23
- package/dist/types/utility/runtime/index.d.ts +0 -5
- package/dist/types/utility/runtime/type.d.ts +0 -27
- package/dist/types/utility/runtime/withValue.d.ts +0 -19
- package/dist/types/utility/state/Configurator.d.ts +0 -36
- package/dist/types/utility/state/FluentConfigurator.d.ts +0 -27
- package/dist/types/utility/state/index.d.ts +0 -3
- package/src/types/alphabetic/Intrinsic.ts +0 -6
- package/src/utility/modelling/IoModel.ts +0 -38
- package/tests/FluentApi-spec.ts +0 -90
- package/tests/FluentConfigurator-spec.hold +0 -88
- package/tests/IoModel-spec.hold +0 -209
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { FluentConfigurator, keys } from "../src";
|
|
2
|
-
import { mySong, Playlist, Song } from "./data/index";
|
|
3
|
-
import { SimpleTable } from "./data/SimpleTable";
|
|
4
|
-
|
|
5
|
-
describe("Configurator => ", () => {
|
|
6
|
-
it("Call to configurator returns API", () => {
|
|
7
|
-
const c = FluentConfigurator();
|
|
8
|
-
expect(typeof c.done).toBe("function");
|
|
9
|
-
expect(typeof c.done()).toBe("object");
|
|
10
|
-
expect(Object.keys(c.done())).toHaveLength(0);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("Configurator with empty initial state, can have props added using set() and fluent API style", () => {
|
|
14
|
-
const c = FluentConfigurator().set("a", 5).set("b", "foobar").done();
|
|
15
|
-
expect(c).toHaveProperty("a");
|
|
16
|
-
expect(typeof c.a).toBe("number");
|
|
17
|
-
expect(c).toHaveProperty("b");
|
|
18
|
-
expect(typeof c.b).toBe("string");
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("Configurator with starting state, can have props added using fluent API style", () => {
|
|
22
|
-
const start = { foo: "bar", bar: "baz" };
|
|
23
|
-
const c = FluentConfigurator(start).set("b", "foobar").set("a", 5).done();
|
|
24
|
-
console.log(keys(c));
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// added state
|
|
28
|
-
expect(c).toHaveProperty("a", 5);
|
|
29
|
-
expect(typeof c.a).toBe("number");
|
|
30
|
-
expect(c).toHaveProperty("b", "foobar");
|
|
31
|
-
expect(typeof c.b).toBe("string");
|
|
32
|
-
|
|
33
|
-
// starting state
|
|
34
|
-
expect(c).toHaveProperty("foo");
|
|
35
|
-
// TODO: need to ensure initial state is available to type system
|
|
36
|
-
// expect(typeof c.foo).toBe("string");
|
|
37
|
-
// expect(c.foo).toBe(start.foo);
|
|
38
|
-
expect(c).toHaveProperty("bar");
|
|
39
|
-
// expect(typeof c.bar).toBe("string");
|
|
40
|
-
// expect(c.bar).toBe(start.bar);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("Configurator stores Table objects and keeps the typing", () => {
|
|
44
|
-
const c = FluentConfigurator()
|
|
45
|
-
.set("songs", SimpleTable(Song))
|
|
46
|
-
.set("playlists", SimpleTable(Playlist))
|
|
47
|
-
.done();
|
|
48
|
-
// structure
|
|
49
|
-
expect(c).toHaveProperty("songs");
|
|
50
|
-
expect(c.songs).toHaveProperty("is");
|
|
51
|
-
expect(c.songs).toHaveProperty("select");
|
|
52
|
-
expect(c).toHaveProperty("playlists");
|
|
53
|
-
expect(c.playlists).toHaveProperty("is");
|
|
54
|
-
expect(c.playlists).toHaveProperty("select");
|
|
55
|
-
// type guards
|
|
56
|
-
// TODO: get back to working types
|
|
57
|
-
expect((c.songs as any).is(mySong)).toBe(true);
|
|
58
|
-
expect((c.songs as any).is({ foo: false })).toBe(false);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("set() function is able to set a simple value and have type retained", () => {
|
|
62
|
-
const c = FluentConfigurator()
|
|
63
|
-
.set("songs", SimpleTable(Song))
|
|
64
|
-
.set("playlists", SimpleTable(Playlist))
|
|
65
|
-
.set("foo", 15)
|
|
66
|
-
.set("bar", 1);
|
|
67
|
-
const t = c.done();
|
|
68
|
-
// TODO: get back to working types
|
|
69
|
-
expect((t.songs as any).is(mySong)).toBe(true);
|
|
70
|
-
expect((t.songs as any).is({ foo: false })).toBe(false);
|
|
71
|
-
expect(typeof t.songs).toBe("object");
|
|
72
|
-
expect(typeof t.playlists).toBe("object");
|
|
73
|
-
expect(typeof t.foo).toBe("number");
|
|
74
|
-
expect(typeof t.bar).toBe("number");
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("a partially typed configurator can be configured with set()", () => {
|
|
78
|
-
const c = FluentConfigurator<{ songs: object; playlists: object }>()
|
|
79
|
-
.set("songs", SimpleTable(Song))
|
|
80
|
-
.set("playlists", SimpleTable(Playlist))
|
|
81
|
-
.set("foobar", true)
|
|
82
|
-
.done();
|
|
83
|
-
|
|
84
|
-
expect(c.songs.name).toBe("Song");
|
|
85
|
-
expect(c.playlists.name).toBe("Playlist");
|
|
86
|
-
expect(c.foobar).toBe(true);
|
|
87
|
-
});
|
|
88
|
-
});
|
package/tests/IoModel-spec.hold
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import * as t from "io-ts";
|
|
2
|
-
import { isLeft, isRight } from "fp-ts/Either";
|
|
3
|
-
import {
|
|
4
|
-
Equal,
|
|
5
|
-
NotEqual,
|
|
6
|
-
Expect,
|
|
7
|
-
ExpectExtends,
|
|
8
|
-
ExpectFalse,
|
|
9
|
-
ExpectTrue,
|
|
10
|
-
} from "@type-challenges/utils";
|
|
11
|
-
import { IoModel } from "~/utility";
|
|
12
|
-
|
|
13
|
-
export const mySong = {
|
|
14
|
-
artist: "Billy Idol",
|
|
15
|
-
song: "Whiplash Smile",
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const SongMeta = t.partial({ year: t.number, genre: t.string });
|
|
19
|
-
const req = { name: t.string, artist: t.string };
|
|
20
|
-
const optional = { album: t.string, meta: SongMeta };
|
|
21
|
-
|
|
22
|
-
const Song = IoModel("Song", req, optional);
|
|
23
|
-
type SongType = t.TypeOf<typeof Song>;
|
|
24
|
-
const goodSong = { name: "My Song", artist: "Elton John" };
|
|
25
|
-
const badSong = { name: "Tom Fuckery" };
|
|
26
|
-
|
|
27
|
-
const playReq = { name: t.string, owner: t.string };
|
|
28
|
-
/** note that `Playlist` only has required props */
|
|
29
|
-
const Playlist = IoModel("Playlist", playReq);
|
|
30
|
-
type PlaylistType = t.TypeOf<typeof Playlist>;
|
|
31
|
-
const goodPlaylist = { name: "a jumble of songs", owner: "Kris Kross" };
|
|
32
|
-
const extraPlaylist = { name: "if only", owner: "fake dude", badProp: true };
|
|
33
|
-
const badPlaylist = { name: "if only", owner: 42 };
|
|
34
|
-
|
|
35
|
-
describe("Model configurator => ", () => {
|
|
36
|
-
it("Model function returns a model which can be converted to a type with t.TypeOf", () => {
|
|
37
|
-
// manual creation of a model
|
|
38
|
-
const model = t.intersection([t.type(req), t.partial(optional)], "Song");
|
|
39
|
-
type M = t.TypeOf<typeof model>;
|
|
40
|
-
type cases = [
|
|
41
|
-
Expect<Equal<SongType["name"], M["name"]>>,
|
|
42
|
-
Expect<Equal<SongType["album"], M["album"]>>,
|
|
43
|
-
Expect<Equal<SongType["artist"], M["artist"]>>
|
|
44
|
-
];
|
|
45
|
-
const typeTests: cases = [true, true, true];
|
|
46
|
-
expect(typeTests).toBe(typeTests);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("Model's name is a literal type, not a string", () => {
|
|
50
|
-
type cases = [
|
|
51
|
-
Expect<NotEqual<typeof Song["name"], "string">>,
|
|
52
|
-
Expect<Equal<typeof Song["name"], "Song">>,
|
|
53
|
-
Expect<NotEqual<typeof Playlist["name"], "string">>,
|
|
54
|
-
Expect<Equal<typeof Playlist["name"], "Playlist">>
|
|
55
|
-
];
|
|
56
|
-
const typeTests: cases = [true, true, true, true];
|
|
57
|
-
expect(typeTests).toBe(typeTests);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("Model function returns a model who's type guard works as expected", () => {
|
|
61
|
-
expect(Song.is(goodSong)).toBe(true);
|
|
62
|
-
expect(Song.is(badSong)).toBe(false);
|
|
63
|
-
expect(Playlist.is(goodPlaylist)).toBe(true);
|
|
64
|
-
expect(Playlist.is(badPlaylist)).toBe(false);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("extra model properties pass the type guard but extra prop is not part of type", () => {
|
|
68
|
-
expect(Playlist.is(extraPlaylist)).toBe(true);
|
|
69
|
-
if (Playlist.is(extraPlaylist)) {
|
|
70
|
-
type E = typeof extraPlaylist;
|
|
71
|
-
type cases = [
|
|
72
|
-
Expect<ExpectExtends<keyof E, keyof PlaylistType>>,
|
|
73
|
-
Expect<NotEqual<E, PlaylistType>>,
|
|
74
|
-
Expect<Equal<keyof E, "name" | "owner" | "badProp">>,
|
|
75
|
-
Expect<NotEqual<keyof PlaylistType, "name" | "owner" | "badProp">>,
|
|
76
|
-
Expect<Equal<keyof PlaylistType, "name" | "owner">>
|
|
77
|
-
];
|
|
78
|
-
const typeTests: cases = [true, true, true, true, true];
|
|
79
|
-
expect(typeTests).toBe(typeTests);
|
|
80
|
-
} else {
|
|
81
|
-
throw new Error("extra params in object should still pass the type guard!");
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("Model function returns a decoder which works as expected", () => {
|
|
86
|
-
// basics
|
|
87
|
-
expect(Song.decode(goodSong)._tag).toBe("Right");
|
|
88
|
-
expect(Song.decode(badSong)._tag).toBe("Left");
|
|
89
|
-
expect(Playlist.decode(goodPlaylist)._tag).toBe("Right");
|
|
90
|
-
expect(Playlist.decode(extraPlaylist)._tag).toBe("Right");
|
|
91
|
-
expect(Playlist.decode(badPlaylist)._tag).toBe("Left");
|
|
92
|
-
|
|
93
|
-
// addressing extra properties
|
|
94
|
-
const extra = Playlist.decode(extraPlaylist);
|
|
95
|
-
if (isRight(extra)) {
|
|
96
|
-
// model props represented and correct
|
|
97
|
-
expect(extra.right.name).toBe(extraPlaylist.name);
|
|
98
|
-
expect(extra.right.owner).toBe(extraPlaylist.owner);
|
|
99
|
-
// extra props are still there at run time
|
|
100
|
-
expect(Object.keys(extra.right)).toContain("badProp");
|
|
101
|
-
// but they are not available to the type system
|
|
102
|
-
type cases = [ExpectFalse<ExpectExtends<keyof typeof extra, "badProp">>];
|
|
103
|
-
const typeTests: cases = [false];
|
|
104
|
-
expect(typeTests).toBe(typeTests);
|
|
105
|
-
} else {
|
|
106
|
-
throw new Error("decoder asserted a playlist with extra props as being invalid!");
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const invalid = Playlist.decode(badPlaylist);
|
|
110
|
-
if (isLeft(invalid)) {
|
|
111
|
-
type cases = [Expect<ExpectExtends<typeof invalid["left"], t.Errors>>];
|
|
112
|
-
const typeTests: cases = [true];
|
|
113
|
-
expect(typeTests).toBe(typeTests);
|
|
114
|
-
} else {
|
|
115
|
-
throw new Error("decoder asserted a invalid playlist was valid!");
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const valid = Playlist.decode(goodPlaylist);
|
|
119
|
-
if (isRight(valid)) {
|
|
120
|
-
type cases = [Expect<ExpectExtends<typeof valid["right"], PlaylistType>>];
|
|
121
|
-
const typeTests: cases = [true];
|
|
122
|
-
expect(typeTests).toBe(typeTests);
|
|
123
|
-
} else {
|
|
124
|
-
throw new Error("decoder asserted an valid playlist was invalid!");
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("if model is given non PascalCase name it will be converted to PascalCase", () => {
|
|
129
|
-
const simple = IoModel("simple", { name: t.string });
|
|
130
|
-
const camel = IoModel("camelCase", { name: t.string });
|
|
131
|
-
const snake = IoModel("snake_case", { name: t.string });
|
|
132
|
-
const dash = IoModel("dash-case", { name: t.string });
|
|
133
|
-
|
|
134
|
-
expect(simple.name).toBe("Simple");
|
|
135
|
-
expect(camel.name).toBe("CamelCase");
|
|
136
|
-
expect(snake.name).toBe("SnakeCase");
|
|
137
|
-
expect(dash.name).toBe("DashCase");
|
|
138
|
-
|
|
139
|
-
type cases = [
|
|
140
|
-
ExpectTrue<Equal<typeof simple["name"], "Simple">>,
|
|
141
|
-
ExpectTrue<Equal<typeof camel["name"], "CamelCase">>,
|
|
142
|
-
ExpectTrue<Equal<typeof snake["name"], "SnakeCase">>,
|
|
143
|
-
ExpectTrue<Equal<typeof dash["name"], "DashCase">>
|
|
144
|
-
];
|
|
145
|
-
const typeTests: cases = [true, true, true, true];
|
|
146
|
-
expect(typeTests).toBe(typeTests);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("Models put into an array can be retrieved in full fidelity", () => {
|
|
150
|
-
const arr = [Song, Playlist];
|
|
151
|
-
|
|
152
|
-
// this will resolve to a union of Song and Playlist model structures
|
|
153
|
-
type Union = SongType | PlaylistType;
|
|
154
|
-
|
|
155
|
-
for (const m of arr) {
|
|
156
|
-
// run-time has a string for name
|
|
157
|
-
expect(typeof m.name).toBe("string");
|
|
158
|
-
|
|
159
|
-
// I naive assumption would be that this would be a distinctly typed
|
|
160
|
-
// type structure for the underlying model but each element of the array
|
|
161
|
-
// is -- in fact -- still just a union of SongType and PlaylistType
|
|
162
|
-
type NaiveUnion = t.TypeOf<typeof m>;
|
|
163
|
-
|
|
164
|
-
// @ts-ignore
|
|
165
|
-
type cases = [
|
|
166
|
-
// type system extends from "string"
|
|
167
|
-
Expect<ExpectExtends<string, typeof m.name>>,
|
|
168
|
-
// but is a string literal (aka, narrower than a string in definition)
|
|
169
|
-
Expect<NotEqual<typeof m.name, string>>,
|
|
170
|
-
// the overall data structure extends from IModel
|
|
171
|
-
Expect<ExpectExtends<IoModel<any, any>, typeof m>>,
|
|
172
|
-
// adding in the literal name should cause no harm
|
|
173
|
-
Expect<ExpectExtends<IoModel<any, typeof m.name>, typeof m>>,
|
|
174
|
-
// unfortunately, since we still don't know which of the models
|
|
175
|
-
// we're dealing with, we can't test the fidelity of the underlying
|
|
176
|
-
// model's TS typing
|
|
177
|
-
Expect<Equal<NaiveUnion, Union>>
|
|
178
|
-
];
|
|
179
|
-
|
|
180
|
-
// Because the `name` property is a literal type (versus just a string),
|
|
181
|
-
// however, the Union types we've been dealing with are still _distinct_
|
|
182
|
-
// for each model is not lost. This allows us to use a simple conditional
|
|
183
|
-
// logic and get full type fidelity
|
|
184
|
-
if (m.name === "Song") {
|
|
185
|
-
type SpecificModel = t.TypeOf<typeof m>;
|
|
186
|
-
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
type cases = [
|
|
189
|
-
// the specific model will extend the union
|
|
190
|
-
Expect<ExpectExtends<Union, SpecificModel>>,
|
|
191
|
-
// but is no longer equal as it's type has been narrowed by inference
|
|
192
|
-
Expect<NotEqual<SpecificModel, Union>>
|
|
193
|
-
];
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (m.name === "Playlist") {
|
|
197
|
-
type SpecificModel = t.TypeOf<typeof m>;
|
|
198
|
-
|
|
199
|
-
// @ts-ignore
|
|
200
|
-
type cases = [
|
|
201
|
-
// the specific model will extend the union
|
|
202
|
-
Expect<ExpectExtends<Union, SpecificModel>>,
|
|
203
|
-
// but is no longer equal as it's type has been narrowed by inference
|
|
204
|
-
Expect<NotEqual<SpecificModel, Union>>
|
|
205
|
-
];
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
});
|