-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
hook-types-test.tsx
118 lines (101 loc) · 3.65 KB
/
hook-types-test.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import type { TypedResponse } from "../serialize";
import type { useLoaderData } from "../components";
function isEqual<A, B>(
arg: A extends B ? (B extends A ? true : false) : false
): void {}
// not sure why `eslint` thinks the `T` generic is not used...
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type LoaderData<T> = ReturnType<typeof useLoaderData<T>>;
describe("useLoaderData", () => {
it("supports plain data type", () => {
type AppData = { hello: string };
type response = LoaderData<AppData>;
isEqual<response, { hello: string }>(true);
});
it("supports plain Response", () => {
type Loader = (args: any) => Response;
type response = LoaderData<Loader>;
isEqual<response, any>(true);
});
it("infers type regardless of redirect", () => {
type Loader = (
args: any
) => TypedResponse<{ id: string }> | TypedResponse<never>;
type response = LoaderData<Loader>;
isEqual<response, { id: string }>(true);
});
it("supports Response-returning loader", () => {
type Loader = (args: any) => TypedResponse<{ hello: string }>;
type response = LoaderData<Loader>;
isEqual<response, { hello: string }>(true);
});
it("supports async Response-returning loader", () => {
type Loader = (args: any) => Promise<TypedResponse<{ hello: string }>>;
type response = LoaderData<Loader>;
isEqual<response, { hello: string }>(true);
});
it("supports data-returning loader", () => {
type Loader = (args: any) => { hello: string };
type response = LoaderData<Loader>;
isEqual<response, { hello: string }>(true);
});
it("supports async data-returning loader", () => {
type Loader = (args: any) => Promise<{ hello: string }>;
type response = LoaderData<Loader>;
isEqual<response, { hello: string }>(true);
});
});
describe("type serializer", () => {
it("converts Date to string", () => {
type AppData = { hello: Date };
type response = LoaderData<AppData>;
isEqual<response, { hello: string }>(true);
});
it("supports custom toJSON", () => {
type AppData = { toJSON(): { data: string[] } };
type response = LoaderData<AppData>;
isEqual<response, { data: string[] }>(true);
});
it("supports recursion", () => {
type AppData = { dob: Date; parent: AppData };
type SerializedAppData = { dob: string; parent: SerializedAppData };
type response = LoaderData<AppData>;
isEqual<response, SerializedAppData>(true);
});
it("supports tuples and arrays", () => {
type AppData = { arr: Date[]; tuple: [string, number, Date]; empty: [] };
type response = LoaderData<AppData>;
isEqual<
response,
{ arr: string[]; tuple: [string, number, string]; empty: [] }
>(true);
});
it("transforms unserializables to null in arrays", () => {
type AppData = [Function, symbol, undefined];
type response = LoaderData<AppData>;
isEqual<response, [null, null, null]>(true);
});
it("transforms unserializables to never in objects", () => {
type AppData = { arg1: Function; arg2: symbol; arg3: undefined };
type response = LoaderData<AppData>;
isEqual<response, {}>(true);
});
it("supports class instances", () => {
class Test {
arg: string;
speak: () => string;
}
type Loader = (args: any) => TypedResponse<Test>;
type response = LoaderData<Loader>;
isEqual<response, { arg: string }>(true);
});
it("makes keys optional if the value is undefined", () => {
type AppData = {
arg1: string;
arg2: number | undefined;
arg3: undefined;
};
type response = LoaderData<AppData>;
isEqual<response, { arg1: string; arg2?: number }>(true);
});
});