inferred-types 0.20.0 → 0.22.5
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/.eslintrc +36 -20
- package/.github/workflows/main.yml +34 -0
- package/.github/workflows/other.yml +15 -0
- package/.vscode/settings.json +10 -2
- package/dist/index.d.ts +426 -8547
- package/dist/index.js +57 -76
- package/dist/index.mjs +47 -63
- package/package.json +38 -26
- package/src/Mutation/index.ts +6 -29
- package/src/index.ts +6 -29
- package/src/shared/index.ts +6 -29
- package/src/shared/valueTypes.ts +1 -1
- package/src/types/ExpandRecursively.ts +10 -1
- package/src/types/Keys.ts +10 -6
- package/src/types/SimplifyObject.ts +12 -0
- package/src/types/Transformer.ts +1 -1
- package/src/types/alphabetic/CamelCase.ts +2 -2
- package/src/types/alphabetic/CapFirstAlpha.ts +7 -3
- package/src/types/alphabetic/Dasherize.ts +8 -5
- package/src/types/alphabetic/KebabCase.ts +1 -1
- package/src/types/alphabetic/PascalCase.ts +3 -1
- package/src/types/alphabetic/SnakeCase.ts +8 -3
- package/src/types/alphabetic/alpha-characters.ts +33 -9
- package/src/types/alphabetic/index.ts +6 -29
- package/src/types/dictionary/DictChangeValue.ts +26 -0
- package/src/types/dictionary/DictPartialApplication.ts +30 -0
- package/src/types/dictionary/DictPrependWithFn.ts +23 -0
- package/src/types/dictionary/DictReturnValues.ts +27 -0
- package/src/types/dictionary/MutableProps.ts +19 -0
- package/src/types/dictionary/RequireProps.ts +15 -0
- package/src/types/{type-conversion → dictionary}/SameKeys.ts +0 -0
- package/src/types/dictionary/index.ts +13 -30
- package/src/types/{props.ts → dictionary/props.ts} +2 -2
- package/src/types/fluent/index.ts +6 -29
- package/src/types/functions/FinalReturn.ts +12 -0
- package/src/types/functions/index.ts +12 -0
- package/src/types/index.ts +8 -30
- package/src/types/kv/index.ts +6 -29
- package/src/types/lists/index.ts +6 -29
- package/src/types/ruleset-types.ts +3 -3
- package/src/types/runtime.ts +18 -18
- package/src/types/string-literals/LeftWhitespace.ts +5 -2
- package/src/types/string-literals/RightWhitespace.ts +5 -2
- package/src/types/string-literals/index.ts +6 -29
- package/src/types/tuples/FirstKey.ts +3 -3
- package/src/types/tuples/FromDictArray.ts +5 -4
- package/src/types/tuples/index.ts +6 -29
- package/src/types/type-conversion/index.ts +6 -32
- package/src/utility/api/api.ts +8 -7
- package/src/utility/api/index.ts +6 -29
- package/src/utility/dictionary/defineProperties.ts +35 -0
- package/src/utility/dictionary/dictionaryTransform.ts +5 -4
- package/src/utility/dictionary/entries.ts +9 -5
- package/src/utility/dictionary/index.ts +7 -30
- package/src/utility/dictionary/kv/dictToKv.ts +5 -3
- package/src/utility/dictionary/kv/filterDictArray.ts +5 -7
- package/src/utility/dictionary/kv/index.ts +6 -29
- package/src/utility/dictionary/kv/kv.ts +8 -3
- package/src/utility/dictionary/kv/kvToDict.ts +3 -2
- package/src/utility/dictionary/mapValues.ts +8 -5
- package/src/utility/dictionary/strArrayToDict.ts +1 -2
- package/src/utility/errors/ReadOnlyViolation.ts +3 -0
- package/src/utility/errors/index.ts +12 -0
- package/src/utility/index.ts +7 -29
- package/src/utility/keys.ts +8 -4
- package/src/utility/lists/groupBy.ts +2 -9
- package/src/utility/lists/index.ts +6 -29
- package/src/utility/literals/arrayToObject.ts +29 -29
- package/src/utility/literals/defineType.ts +6 -6
- package/src/utility/literals/identity.ts +5 -2
- package/src/utility/literals/index.ts +6 -29
- package/src/utility/literals/literal.ts +3 -3
- package/src/utility/map-reduce/index.ts +6 -29
- package/src/utility/modelling/index.ts +6 -29
- package/src/utility/ruleset.ts +11 -9
- package/src/utility/runtime/condition.ts +1 -1
- package/src/utility/runtime/conditions/index.ts +6 -30
- package/src/utility/runtime/conditions/isFalse.ts +2 -2
- package/src/utility/runtime/conditions/isFunction.ts +2 -2
- package/src/utility/runtime/conditions/isObject.ts +4 -1
- package/src/utility/runtime/conditions/isTrue.ts +1 -1
- package/src/utility/runtime/ifTypeOf.ts +5 -4
- package/src/utility/runtime/index.ts +6 -29
- package/src/utility/runtime/type.ts +3 -1
- package/src/utility/runtime/withValue.ts +5 -3
- package/src/utility/state/Configurator.ts +2 -2
- package/src/utility/state/FluentConfigurator.ts +2 -2
- package/src/utility/state/index.ts +6 -30
- package/tests/CamelCase-spec.ts +2 -0
- package/tests/ExplicitFunction-spec.ts +3 -2
- package/tests/IncludeAndRetain-spec.ts +7 -12
- package/tests/Includes-spec.ts +2 -0
- package/tests/KebabCase-spec.ts +2 -0
- package/tests/MutationIdentity-spec.ts +2 -1
- package/tests/PascalCase-spec.ts +2 -0
- package/tests/Pluralize-spec.ts +2 -0
- package/tests/SnakeCase-spec.ts +2 -0
- package/tests/Where.spec.ts +9 -10
- package/tests/arrayToKeyLookup-spec.ts +5 -5
- package/tests/arrayToObject-spec.ts +12 -8
- package/tests/constructor.spec.ts +2 -0
- package/tests/createFnWithProps.spec.ts +2 -2
- package/tests/data/index.ts +6 -29
- package/tests/defineType-spec.ts +17 -11
- package/tests/dictionary/DictChangeValue.test.ts +30 -0
- package/tests/dictionary/DictPartialApplication.test.ts +43 -0
- package/tests/dictionary/DictReturnValues.test.ts +36 -0
- package/tests/dictionary/Get.spec.ts +5 -3
- package/tests/dictionary/MutableProps.test.ts +30 -0
- package/tests/dictionary/PrependValuesWithFunction.ts +34 -0
- package/tests/dictionary/RequireProps.test.ts +21 -0
- package/tests/dictionaryTransform-spec.ts +3 -3
- package/tests/ifTypeOf-spec.ts +31 -20
- package/tests/kv/KeyValue-spec.ts +4 -4
- package/tests/kv/SameKeys-spec.ts +6 -9
- package/tests/kv/dict-to-kv-and-back.spec.ts +5 -4
- package/tests/kv/entries-spec.ts +8 -9
- package/tests/kv/keys.spec.ts +9 -19
- package/tests/kv/kv-spec.ts +4 -4
- package/tests/lists/UniqueForProp.spec.ts +3 -1
- package/tests/literal-spec.ts +5 -3
- package/tests/mapValues-spec.ts +5 -3
- package/tests/props-spec.ts +3 -2
- package/tests/runtime/condition.spec.ts +2 -1
- package/tests/runtime/type.spec.ts +4 -3
- package/tests/strArrayToDict-spec.ts +6 -6
- package/tests/string-literals/AllCaps.spec.ts +6 -15
- package/tests/string-literals/CamelCase.spec.ts +13 -32
- package/tests/string-literals/Dasherize.spec.ts +13 -31
- package/tests/string-literals/HasUppercase.spec.ts +6 -15
- package/tests/string-literals/PascalCase.spec.ts +13 -32
- package/tests/string-literals/SnakeCase.spec.ts +13 -32
- package/tests/string-literals/whitespace-capture.spec.ts +10 -28
- package/tests/tuples/TupleToUnion.spec.ts +3 -1
- package/tests/withValue.spec.ts +4 -3
- package/tsconfig.json +8 -19
- package/vitest.config.ts +13 -0
- package/jest.config.ts +0 -20
- package/on-hold/Builder/Builder.ts +0 -66
- package/on-hold/Builder/BuilderApi.ts +0 -21
- package/on-hold/Builder/IdentityToMutationApi.ts +0 -44
- package/on-hold/Builder/MutationToFluentApi.ts +0 -60
- package/on-hold/Builder/index.ts +0 -35
- package/on-hold/tests/Builder-spec.ts +0 -310
- package/on-hold/tests/RuleSet-spec.ts +0 -59
- package/on-hold/tests/ToFluent-spec.ts +0 -60
- package/on-hold/tests/api-spec.ts +0 -73
- package/on-hold/tests/data/builder-data.ts +0 -53
- package/on-hold/tests/filterDictArray-spec.ts +0 -50
- package/on-hold/tests/run-time-spec.ts +0 -44
- package/on-hold/type.ts +0 -20
- package/on-hold/types/index.ts +0 -34
- package/on-hold/types/object.ts +0 -19
- package/on-hold/types/prop.ts +0 -28
- package/on-hold/types/scalar.ts +0 -37
- package/src/types/dictionary/NotEmptyObject.ts +0 -9
- package/src/types/type-conversion/UnwrapValue.ts +0 -13
- package/src/types/type-conversion/WrapValue.ts +0 -15
- package/src/utility/dictionary/valuesOfProp.ts +0 -13
- package/src/utility/runtime/conditions/isLiteral.ts +0 -7
- package/src/utility/state/KeyStorage.ts +0 -23
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { RuleSet } from "~/utility";
|
|
3
|
-
type State = { foo: number; bar: number; baz: { a: number; b: number } };
|
|
4
|
-
const rules1 = { foo: true, bar: true, yup: () => true, nope: () => false, maybe: (s: State) => s.foo > 5 } as const;
|
|
5
|
-
import { Equal, Expect } from "@type-challenges/utils";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
describe("RuleSet", () => {
|
|
9
|
-
|
|
10
|
-
it("stages of application produce correct signatures", () => {
|
|
11
|
-
const s1 = RuleSet<State>();
|
|
12
|
-
type S1 = typeof s1;
|
|
13
|
-
const s2 = s1(rules1);
|
|
14
|
-
const sl2 = s1({ foo: true, bar: true, yup: () => true, nope: () => false, maybe: (s: State) => s.foo > 5 });
|
|
15
|
-
type S2 = typeof s2;
|
|
16
|
-
type SL2 = typeof sl2;
|
|
17
|
-
const s3 = s2({ foo: 8, bar: 0, baz: { a: 1, b: 2 } });
|
|
18
|
-
type S3 = typeof s3;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
type cases = [
|
|
22
|
-
// the types returned by the 2nd function call should
|
|
23
|
-
// always be narrow in type definition, even if not explicitly
|
|
24
|
-
// stated as as `as const`.
|
|
25
|
-
// critically we we want to distinguish "true" from "false"
|
|
26
|
-
Expect<Equal<S2, SL2>>,
|
|
27
|
-
// at the end we need to arrive at a type which is a string
|
|
28
|
-
// literal representing the key values which have passed the
|
|
29
|
-
// rules.
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("dynamic rules are evaluated correctly", () => {
|
|
35
|
-
const noState = RuleSet<State>()(rules1)();
|
|
36
|
-
type NoState = typeof noState;
|
|
37
|
-
const maybePassing = RuleSet<State>()(rules1)({ foo: 8, bar: 0, baz: { a: 1, b: 2 } });
|
|
38
|
-
type Pass = typeof maybePassing;
|
|
39
|
-
const maybeFailing = RuleSet<State>()(rules1)({ foo: 0, bar: 0, baz: { a: 1, b: 2 } });
|
|
40
|
-
type Fail = typeof maybeFailing;
|
|
41
|
-
|
|
42
|
-
type cases = [
|
|
43
|
-
// if no state is passed then only static rules are passed forward
|
|
44
|
-
Expect<Equal<NoState, "foo" | "bar">>,
|
|
45
|
-
// "foo" is greater than 5 so results in "maybe" being truthy
|
|
46
|
-
Expect<Equal<Pass, "foo" | "bar" | "yup" | "maybe">>,
|
|
47
|
-
// "foo" is less than 5 and therefore "maybe" is falsy
|
|
48
|
-
Expect<Equal<Fail, "foo" | "bar" | "yup">>,
|
|
49
|
-
];
|
|
50
|
-
const cases: cases = [true, true, true];
|
|
51
|
-
expect(cases).toBe(cases);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("static rulesets operate to exclude parts of an api", () => {
|
|
55
|
-
// const rules1 = RuleSet()({ foo: true })();
|
|
56
|
-
// const rules2 = RuleSet()({ foo: true, baz: true })();
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
});
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import type { Expect, Equal, ExpectExtends } from "@type-challenges/utils";
|
|
2
|
-
import { Keys, ToFluent } from "~/types";
|
|
3
|
-
import { BuilderState } from "./data";
|
|
4
|
-
|
|
5
|
-
const api = {
|
|
6
|
-
foo: () => 5,
|
|
7
|
-
bar: () => "hi",
|
|
8
|
-
baz: (greeting: string) => greeting,
|
|
9
|
-
};
|
|
10
|
-
type Api = typeof api;
|
|
11
|
-
type Fluent = ToFluent<Api>;
|
|
12
|
-
|
|
13
|
-
describe("ToFluent<T,X> type utility", () => {
|
|
14
|
-
it("a simple function-based API has it's return types changed to point back to API", () => {
|
|
15
|
-
type cases = [
|
|
16
|
-
// all return types on the API return the same Fluent API
|
|
17
|
-
Expect<Equal<Fluent, ReturnType<Fluent["foo"]>>>,
|
|
18
|
-
Expect<Equal<Fluent, ReturnType<Fluent["bar"]>>>,
|
|
19
|
-
Expect<Equal<Fluent, ReturnType<Fluent["baz"]>>>,
|
|
20
|
-
// this is also true recursively
|
|
21
|
-
Expect<Equal<Fluent, ReturnType<ReturnType<Fluent["foo"]>["bar"]>>>
|
|
22
|
-
];
|
|
23
|
-
const cases: cases = [true, true, true, true];
|
|
24
|
-
expect(cases).toBe(cases);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// this allows for non fluent parts of the API to be continued on too as part of fluent
|
|
28
|
-
// process.
|
|
29
|
-
it("an API <T> can be made fluent but while including the type <X> as part of the return type", () => {
|
|
30
|
-
const x = {
|
|
31
|
-
hi: () => "hello",
|
|
32
|
-
};
|
|
33
|
-
type X = typeof x;
|
|
34
|
-
type FluentX = ToFluent<Api, X>;
|
|
35
|
-
|
|
36
|
-
type cases = [
|
|
37
|
-
// all return types on the API return the same Fluent API
|
|
38
|
-
Expect<Equal<FluentX, ReturnType<FluentX["foo"]>>>,
|
|
39
|
-
Expect<Equal<FluentX, ReturnType<FluentX["bar"]>>>,
|
|
40
|
-
Expect<Equal<FluentX, ReturnType<FluentX["baz"]>>>,
|
|
41
|
-
// this is also true recursively
|
|
42
|
-
Expect<Equal<FluentX, ReturnType<ReturnType<FluentX["foo"]>["bar"]>>>,
|
|
43
|
-
// the non-fluent API also shows up
|
|
44
|
-
Expect<ExpectExtends<Keys<FluentX>, "hi">>,
|
|
45
|
-
// the "hi" function returns a string (and breaks out of the fluent loop)
|
|
46
|
-
Expect<Equal<string, ReturnType<FluentX["hi"]>>>
|
|
47
|
-
];
|
|
48
|
-
const cases: cases = [true, true, true, true, true, true];
|
|
49
|
-
expect(cases).toBe(cases);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("using API structures similar to a builder", () => {
|
|
53
|
-
const identityApi = {
|
|
54
|
-
incFoo: <T extends Partial<BuilderState>, T2 extends Partial<BuilderState>>(s: T) => () => ({ ...s, foo: s.foo ? s.foo : 1 } as T2),
|
|
55
|
-
decBar: <T extends Partial<BuilderState>>(s: T) => () => ({ ...s, foo: s.foo ? s.foo : 1 } as T),
|
|
56
|
-
};
|
|
57
|
-
const escapeApi = {};
|
|
58
|
-
type Escape<T extends object = {}> = { unwrap: () => BuilderState; current: Partial<BuilderState> } & T;
|
|
59
|
-
});
|
|
60
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { Equal, Expect } from "@type-challenges/utils";
|
|
2
|
-
import { Api, PrivateKeys, PublicKeys } from "~/types";
|
|
3
|
-
import { defineType } from "~/utility";
|
|
4
|
-
import { api } from "~/utility/api/api";
|
|
5
|
-
|
|
6
|
-
describe("Api<T> type", () => {
|
|
7
|
-
it("PublicKeys<T> and PrivateKeys<T> type utils extract the right keys", () => {
|
|
8
|
-
const api = {
|
|
9
|
-
_state: 123,
|
|
10
|
-
_name: "hey ho",
|
|
11
|
-
greet: "hi",
|
|
12
|
-
age: 12,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const f = string;
|
|
16
|
-
|
|
17
|
-
type Test = typeof api;
|
|
18
|
-
type Private = PrivateKeys<Test>;
|
|
19
|
-
type Public = PublicKeys<Test>;
|
|
20
|
-
|
|
21
|
-
type cases = [
|
|
22
|
-
Expect<Equal<Private, "_state" | "_name">>,
|
|
23
|
-
Expect<Equal<Public, "greet" | "age">>
|
|
24
|
-
];
|
|
25
|
-
const cases: cases = [true, true];
|
|
26
|
-
expect(cases).toBe(cases);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it.skip("privateApi() creates a definition for a private API", () => {
|
|
30
|
-
const food = api({ _model: "food", _description: "let's eat" })({
|
|
31
|
-
category: string,
|
|
32
|
-
stars: 5 as number,
|
|
33
|
-
});
|
|
34
|
-
const pub = food();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("The Api<T> utility hides all private keys while preserving type info", () => {
|
|
38
|
-
const simple = {
|
|
39
|
-
_state: 123,
|
|
40
|
-
_name: "hey ho",
|
|
41
|
-
greet: "hi",
|
|
42
|
-
age: 12,
|
|
43
|
-
};
|
|
44
|
-
type Simple = Api<typeof simple>;
|
|
45
|
-
|
|
46
|
-
const midling = defineType({ id: 123 })({
|
|
47
|
-
_state: 123,
|
|
48
|
-
_name: "hey ho",
|
|
49
|
-
greet: "hi",
|
|
50
|
-
age: 12,
|
|
51
|
-
});
|
|
52
|
-
type Midling = Api<typeof midling>;
|
|
53
|
-
|
|
54
|
-
const advanced = defineType({ id: 123, _exclude: ["greet"] })({ greet: "hi", age: 12 });
|
|
55
|
-
type Advanced = Api<typeof advanced>;
|
|
56
|
-
|
|
57
|
-
type cases = [
|
|
58
|
-
// a simple API with no literals doesn't need generics
|
|
59
|
-
// to preserve state
|
|
60
|
-
Expect<Equal<Simple, { greet: string; age: number }>>,
|
|
61
|
-
// if the public interface has type literals this is
|
|
62
|
-
// accommodated without any special effort
|
|
63
|
-
Expect<Equal<Midling, { greet: string; age: number; id: 123 }>>,
|
|
64
|
-
Expect<Equal<Midling, { greet: string; age: number; id: 123 }>>
|
|
65
|
-
// in the situation where the private members have
|
|
66
|
-
// literals that need preservation, we need be assured
|
|
67
|
-
// the API implementation can preserve this strong typing
|
|
68
|
-
// However, to start the public API is quite easily preserved
|
|
69
|
-
];
|
|
70
|
-
const cases: cases = [true, true];
|
|
71
|
-
expect(cases).toBe(cases);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { Builder, BuilderApi } from "~/Builder";
|
|
2
|
-
import { isNonNullObject } from "common-types";
|
|
3
|
-
import { TypeGuard } from "~/types";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export type BuilderState = { foo: number; bar: number; baz?: string };
|
|
7
|
-
|
|
8
|
-
const endpoint = BuilderApi<BuilderState>();
|
|
9
|
-
const f0 = endpoint("setFoo", (s) => (n: number) => ({
|
|
10
|
-
...s,
|
|
11
|
-
foo: n,
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
const f1 = endpoint("incFoo", (s) => () => ({
|
|
15
|
-
...s,
|
|
16
|
-
foo: s.foo !== undefined ? s.foo + 1 : 1,
|
|
17
|
-
}));
|
|
18
|
-
const f2 = endpoint("decFoo", (s) => () => ({
|
|
19
|
-
...s,
|
|
20
|
-
foo: s.foo !== undefined ? s.foo - 1 : 0,
|
|
21
|
-
}));
|
|
22
|
-
const f3 = endpoint("setBar", (s) => (n: number) => ({
|
|
23
|
-
...s,
|
|
24
|
-
bar: n,
|
|
25
|
-
}));
|
|
26
|
-
const f4 = endpoint("incBar", (s) => () => ({
|
|
27
|
-
...s,
|
|
28
|
-
bar: s.bar !== undefined ? s.bar + 1 : 1,
|
|
29
|
-
}));
|
|
30
|
-
const f5 = endpoint("setBaz", (s) => (m: string) => ({
|
|
31
|
-
...s,
|
|
32
|
-
baz: m,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
const tg: TypeGuard<BuilderState> = (input: unknown): input is BuilderState => {
|
|
36
|
-
return (
|
|
37
|
-
isNonNullObject(input) &&
|
|
38
|
-
typeof (input as BuilderState).foo === "number" &&
|
|
39
|
-
typeof (input as BuilderState).bar === "number"
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Creates a builder initialized to the state passed in.
|
|
45
|
-
* This builder has foo, bar, and optionally a baz property
|
|
46
|
-
*/
|
|
47
|
-
export function createBuilder<T extends Partial<BuilderState>>(s: T) {
|
|
48
|
-
return Builder(tg, { ...f0, ...f1, ...f2, ...f3, ...f4, ...f5 })(s);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function createStateIdentityApi() {
|
|
52
|
-
return { ...f0, ...f1, ...f2, ...f3, ...f4, ...f5 };
|
|
53
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { defineType, dictToArray, filterDictArray } from "~/utility";
|
|
2
|
-
|
|
3
|
-
describe("filterDictArray()", () => {
|
|
4
|
-
|
|
5
|
-
it("an object converted into a DictArray can be filter down to a subset", () => {
|
|
6
|
-
const obj = defineType({ id: 123 })({ color: "red", favorite: true });
|
|
7
|
-
|
|
8
|
-
const arr = dictToArray(obj);
|
|
9
|
-
|
|
10
|
-
const filtered = filterDictArray(arr, (k, _v) => {
|
|
11
|
-
return k !== "color";
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
// run time tests
|
|
15
|
-
expect(arr).toHaveLength(3);
|
|
16
|
-
expect(filtered).toHaveLength(2);
|
|
17
|
-
expect(filtered.map(i => i[0])).toContain("id");
|
|
18
|
-
expect(filtered.map(i => i[0])).toContain("favorite");
|
|
19
|
-
expect(filtered.map(i => i[0])).not.toContain("color");
|
|
20
|
-
|
|
21
|
-
// TODO: uncomment type test below once working!
|
|
22
|
-
|
|
23
|
-
// type tests
|
|
24
|
-
type cases = [
|
|
25
|
-
// now that "color" has been removed from `T` the type
|
|
26
|
-
// should no longer be the same DictArray
|
|
27
|
-
// ExpectFalse<Equal<Filtered, DictArray<Obj>>>,
|
|
28
|
-
// Expect<Equal<Filtered, DictArray<Omit<Obj, "color">>>>,
|
|
29
|
-
];
|
|
30
|
-
const cases: cases = [];
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
// TODO: return this test once functionality is working correctly
|
|
34
|
-
|
|
35
|
-
it.skip("a filtered down DictArray can be converted back to an object", () => {
|
|
36
|
-
// const obj = defineType({ id: 123 })({ color: "red", favorite: true });
|
|
37
|
-
// type Obj = typeof obj;
|
|
38
|
-
// const arr = dictToArray(obj);
|
|
39
|
-
// type Arr = typeof arr;
|
|
40
|
-
|
|
41
|
-
// const filtered = filterDictArray(arr, (k, _v) => {
|
|
42
|
-
// return k !== "color";
|
|
43
|
-
// });
|
|
44
|
-
// type Filtered = typeof filtered;
|
|
45
|
-
|
|
46
|
-
// const reverted = arrayToDict(filtered);
|
|
47
|
-
// type Reverted = typeof reverted;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
});
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Equal, Expect } from "@type-challenges/utils";
|
|
2
|
-
import { TypeGuard } from "~/types";
|
|
3
|
-
import { number, string } from "~/utility/runtime";
|
|
4
|
-
|
|
5
|
-
describe("run-time types", () => {
|
|
6
|
-
|
|
7
|
-
it("string()", () => {
|
|
8
|
-
const s = string();
|
|
9
|
-
type S = typeof s;
|
|
10
|
-
|
|
11
|
-
expect(s.type).toBe("string");
|
|
12
|
-
|
|
13
|
-
type cases = [
|
|
14
|
-
Expect<Equal<S["__kind"], "type">>,
|
|
15
|
-
Expect<Equal<S["type"], string>>,
|
|
16
|
-
Expect<Equal<S["is"], TypeGuard<string>>>
|
|
17
|
-
];
|
|
18
|
-
const cases: cases = [true, true, true];
|
|
19
|
-
expect(cases).toBe(cases);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("number()", () => {
|
|
23
|
-
const n = number();
|
|
24
|
-
type N = typeof n;
|
|
25
|
-
|
|
26
|
-
expect(n.type).toBe("number");
|
|
27
|
-
|
|
28
|
-
type cases = [
|
|
29
|
-
Expect<Equal<N["__kind"], "type">>,
|
|
30
|
-
Expect<Equal<N["type"], number>>,
|
|
31
|
-
Expect<Equal<N["is"], TypeGuard<number>>>
|
|
32
|
-
];
|
|
33
|
-
const cases: cases = [true, true, true];
|
|
34
|
-
expect(cases).toBe(cases);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("empty object()", () => {
|
|
38
|
-
// const o = object();
|
|
39
|
-
// type O = typeof o;
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
package/on-hold/type.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { TypeGuard } from "~/types";
|
|
2
|
-
import { RuntimeType } from "../../../types/runtime";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Creates a run-time type that is conveyed to Typescript as well
|
|
6
|
-
*/
|
|
7
|
-
export const type =
|
|
8
|
-
<T extends any>() =>
|
|
9
|
-
<N extends string, O extends object>(
|
|
10
|
-
name: N,
|
|
11
|
-
validate: TypeGuard<T>,
|
|
12
|
-
_options: O
|
|
13
|
-
): RuntimeType<T> => {
|
|
14
|
-
return {
|
|
15
|
-
__kind: "type",
|
|
16
|
-
|
|
17
|
-
type: name as unknown as T,
|
|
18
|
-
is: validate,
|
|
19
|
-
};
|
|
20
|
-
};
|
package/on-hold/types/index.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// #autoindex
|
|
2
|
-
// #region autoindexed files
|
|
3
|
-
// index last changed at: 1st Jan, 2022, 03:27 PM ( GMT-8 )
|
|
4
|
-
// hash-code: da242834
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// #endregion
|
|
9
|
-
|
|
10
|
-
// This file was created by running: "dd autoindex"; it assumes you have
|
|
11
|
-
// the 'do-devops' pkg (that's "dd" on npm) installed as a dev dep.
|
|
12
|
-
//
|
|
13
|
-
// By default it assumes that exports are named exports but this can be changed by
|
|
14
|
-
// adding a modifier to the '// #autoindex' syntax:
|
|
15
|
-
//
|
|
16
|
-
// - autoindex:named same as default, exports "named symbols"
|
|
17
|
-
// - autoindex:default assumes each file is exporting a default export and
|
|
18
|
-
// converts the default export to the name of the file
|
|
19
|
-
// - autoindex:offset assumes files export "named symbols" but that each
|
|
20
|
-
// file's symbols should be offset by the file's name
|
|
21
|
-
//
|
|
22
|
-
// You may also exclude certain files or directories by adding it to the
|
|
23
|
-
// autoindex command. As an example:
|
|
24
|
-
//
|
|
25
|
-
// - autoindex:named, exclude: foo,bar,baz
|
|
26
|
-
//
|
|
27
|
-
// Inversely, if you state a file to be an "orphan" then autoindex files
|
|
28
|
-
// below this file will not reference this autoindex file:
|
|
29
|
-
//
|
|
30
|
-
// - autoindex:named, orphan
|
|
31
|
-
//
|
|
32
|
-
// All content outside the "// #region" section in this file will be
|
|
33
|
-
// preserved in situations where you need to do something paricularly awesome.
|
|
34
|
-
// Keep on being awesome.
|
package/on-hold/types/object.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// import type { TypeOptions, TypeGuard } from "~/types";
|
|
2
|
-
// import { type } from "./type";
|
|
3
|
-
|
|
4
|
-
export type ObjectOption<N extends string | undefined> = {
|
|
5
|
-
name?: N;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
// export const object = <N extends string | undefined>(props: PropsCallback, opts: TypeOptions<ObjectOption<N>> = {}) => {
|
|
9
|
-
|
|
10
|
-
// /**
|
|
11
|
-
// * Object based type-guard
|
|
12
|
-
// */
|
|
13
|
-
// const tg: TypeGuard<null> = (v: unknown): v is null => {
|
|
14
|
-
// return v === "null";
|
|
15
|
-
// };
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
// return type<null>()("null", tg, opts);
|
|
19
|
-
// };
|
package/on-hold/types/prop.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { isNonNullObject } from "common-types";
|
|
2
|
-
import { TypeGuard } from "~/types/TypeGuard";
|
|
3
|
-
import { keys } from "~/utility/keys";
|
|
4
|
-
import { RuntimeProp, RuntimeType } from "~/types/runtime";
|
|
5
|
-
|
|
6
|
-
export const prop = <
|
|
7
|
-
P extends PropertyKey,
|
|
8
|
-
T extends RuntimeType<any>,
|
|
9
|
-
O extends object
|
|
10
|
-
>(prop: Readonly<P>, type: Readonly<T>, _opts: O = {} as O): RuntimeProp<P, T> => {
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Default type guard for a property; relies on underlying type's typeguard for validation
|
|
14
|
-
*/
|
|
15
|
-
const tg: TypeGuard<Record<P, T["type"]>> = (v: unknown): v is Record<P, T["type"]> => {
|
|
16
|
-
return isNonNullObject(v) && keys(v as Record<P, any>).includes(prop) && type.is((v as Record<P, any>)[prop as P]);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
__kind: "prop",
|
|
21
|
-
|
|
22
|
-
key: prop,
|
|
23
|
-
valueType: type.type as unknown as Readonly<T["type"]>,
|
|
24
|
-
type: type.type as unknown as Record<P, T["type"]>,
|
|
25
|
-
|
|
26
|
-
is: tg
|
|
27
|
-
};
|
|
28
|
-
};
|
package/on-hold/types/scalar.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { TypeGuard } from "~/types";
|
|
2
|
-
import { TypeOptions } from "../../../types/runtime";
|
|
3
|
-
|
|
4
|
-
export const string = (opts: TypeOptions = {}) => {
|
|
5
|
-
const tg: TypeGuard<string> = (v: unknown): v is string => {
|
|
6
|
-
return typeof v === "string";
|
|
7
|
-
};
|
|
8
|
-
return type<string>()("string", tg, opts);
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const number = (opts: TypeOptions = {}) => {
|
|
12
|
-
const tg: TypeGuard<number> = (v: unknown): v is number => {
|
|
13
|
-
return typeof v === "number";
|
|
14
|
-
};
|
|
15
|
-
return type<number>()("number", tg, opts);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const boolean = (opts: TypeOptions = {}) => {
|
|
19
|
-
const tg: TypeGuard<boolean> = (v: unknown): v is boolean => {
|
|
20
|
-
return typeof v === "boolean";
|
|
21
|
-
};
|
|
22
|
-
return type<boolean>()("string", tg, opts);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const fn = (opts: TypeOptions = {}) => {
|
|
26
|
-
const tg: TypeGuard<Function> = (v: unknown): v is Function => {
|
|
27
|
-
return typeof v === "function";
|
|
28
|
-
};
|
|
29
|
-
return type<Function>()("function", tg, opts);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const nullValue = (opts: TypeOptions = {}) => {
|
|
33
|
-
const tg: TypeGuard<null> = (v: unknown): v is null => {
|
|
34
|
-
return v === "null";
|
|
35
|
-
};
|
|
36
|
-
return type<null>()("null", tg, opts);
|
|
37
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ExpandRecursively } from "../ExpandRecursively";
|
|
2
|
-
import { Keys, Length, UnionToTuple } from "../index";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Accepts an object with at least one property defined on it
|
|
6
|
-
*/
|
|
7
|
-
export type NotEmptyObject<T extends {}> = ExpandRecursively<
|
|
8
|
-
Length<UnionToTuple<Keys<T>>> extends 0 ? false : T
|
|
9
|
-
>;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Given a dictionary of key/values, where the value is a function, this
|
|
4
|
-
* type utility will maintain the keys but change the values to whatever
|
|
5
|
-
* the `ReturnType` of the function was.
|
|
6
|
-
* ```ts
|
|
7
|
-
* // { foo: string }
|
|
8
|
-
* type Test = UnwrapValue<{ foo: (name: string) => name }>
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
|
-
export type UnwrapValue<T extends Record<string, (...args: any[]) => any>> = {
|
|
12
|
-
[K in keyof T]: T[K] extends Function ? ReturnType<T[K]> : never;
|
|
13
|
-
}[keyof T];
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
type ValueFunction<T extends any> = <R extends any>(v: T) => R;
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* **SameKeys**
|
|
5
|
-
*
|
|
6
|
-
* Given a dictionary `T` and a type-strong wrapper function `F`, returns a dictionary with the
|
|
7
|
-
* same keys but
|
|
8
|
-
*
|
|
9
|
-
* Note: meant to be used as part of an _extends_ clause in most cases.
|
|
10
|
-
*/
|
|
11
|
-
export type WrapValue<T extends {}, F extends ValueFunction<T>> = {
|
|
12
|
-
[P in keyof T]: ReturnType<F>;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export type IsLiteral<L extends string | number, T extends any> = T extends L ? true : false;
|
|
2
|
-
|
|
3
|
-
export function isLiteral<L extends Readonly<string>>(...allowed: L[]) {
|
|
4
|
-
return <T extends unknown>(i: T) => {
|
|
5
|
-
return !allowed.every((v) => i !== v) as IsLiteral<L, T>;
|
|
6
|
-
};
|
|
7
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-use-before-define */
|
|
2
|
-
|
|
3
|
-
export type KeyStorage<S extends readonly string[]> = (state: S) => {
|
|
4
|
-
add: <N extends readonly string[]>(...store: N) => KeyStorageApi<readonly [...S, ...N]>;
|
|
5
|
-
remove: <R extends string>(key: R) => KeyStorageApi<Exclude<S, R>>;
|
|
6
|
-
done: () => S;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export type KeyStorageApi<S extends readonly string[]> = ReturnType<KeyStorage<S>>;
|
|
10
|
-
|
|
11
|
-
//TODO: need to make this work or remove
|
|
12
|
-
|
|
13
|
-
export function KeyStorage() {
|
|
14
|
-
const api = <S extends readonly string[]>(state: S) => ({
|
|
15
|
-
add: <N extends readonly string[]>(...store: N) => {
|
|
16
|
-
return api<readonly [...S, ...N]>([...state, ...store]);
|
|
17
|
-
},
|
|
18
|
-
remove: <R extends string>(key: R) => api<Exclude<S, R>>(state.filter(i => i !== key) as unknown as Exclude<S, R>),
|
|
19
|
-
done: () => state
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
return api([]);
|
|
23
|
-
}
|