Skip to content

Commit a235961

Browse files
authored
fix: allow Data to be inferred from Handler function (#2916)
This PR adds support for single-function GET handler data to be inferred when using `define.page<typeof handler>()`. ```ts export const handler = define.handlers((ctx) => { return page({ foo: "foo" }); }); export default define.page<typeof handler>((ctx) => { ctx.data; // Correctly resolves as { foo: string } }); ``` This PR also adds a test that checks that the types inferred are correct by type checking.
1 parent f9bfeca commit a235961

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/define.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { AnyComponent } from "preact";
2-
import type { HandlerByMethod, RouteHandler } from "./handlers.ts";
2+
import type { HandlerByMethod, HandlerFn, RouteHandler } from "./handlers.ts";
33
import type { Middleware } from "./middlewares/mod.ts";
44
import type { PageProps } from "./context.ts";
55

@@ -107,7 +107,9 @@ export interface Define<State> {
107107
page<
108108
// deno-lint-ignore no-explicit-any
109109
Handler extends RouteHandler<any, State> = never,
110-
Data = Handler extends HandlerByMethod<infer Data, State> ? Data : never,
110+
Data = Handler extends HandlerFn<infer Data, State> ? Data
111+
: Handler extends HandlerByMethod<infer Data, State> ? Data
112+
: never,
111113
>(render: AnyComponent<PageProps<Data, State>>): typeof render;
112114

113115
/**

src/define_test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { expect } from "@std/expect";
2+
import { createDefine } from "./define.ts";
3+
import { page } from "./handlers.ts";
4+
5+
Deno.test.ignore("createDefine", () => {
6+
const define = createDefine<{ foo: number }>();
7+
8+
// Testing the types
9+
const handlerFn = define.handlers((ctx) => {
10+
ctx.state.foo satisfies number;
11+
return page({ bar: true });
12+
});
13+
const handlerObj = define.handlers({
14+
GET(ctx) {
15+
ctx.state.foo satisfies number;
16+
return page({ bar: [1, 2, 3] });
17+
},
18+
POST: () => {
19+
return page({ baz: "hello" });
20+
},
21+
});
22+
23+
define.page<typeof handlerFn>(({ data }) => {
24+
data.bar satisfies boolean;
25+
return "page";
26+
});
27+
28+
define.page<typeof handlerObj>(({ data }) => {
29+
if ("baz" in data) {
30+
data.baz satisfies string;
31+
} else {
32+
data.bar satisfies number[];
33+
}
34+
return "page";
35+
});
36+
37+
define.middleware((ctx) => {
38+
ctx.state.foo satisfies number;
39+
return new Response("Hello");
40+
});
41+
42+
expect(typeof define.page).toBe("function");
43+
expect(typeof define.handlers).toBe("function");
44+
expect(typeof define.middleware).toBe("function");
45+
});

0 commit comments

Comments
 (0)