Skip to content

Commit bbbcd2c

Browse files
authored
typegen for future flags (#13506)
* typegen for future flags * remove redundant future flag types from playground
1 parent e2324af commit bbbcd2c

File tree

3 files changed

+69
-20
lines changed

3 files changed

+69
-20
lines changed

.changeset/large-lobsters-grin.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
"@react-router/dev": minor
3+
---
4+
5+
Automatic types for future flags
6+
7+
Some future flags alter the way types should work in React Router.
8+
Previously, you had to remember to manually opt-in to the new types.
9+
10+
For example, for `unstable_middleware`:
11+
12+
```ts
13+
// react-router.config.ts
14+
15+
// Step 1: Enable middleware
16+
export default {
17+
future: {
18+
unstable_middleware: true,
19+
},
20+
};
21+
22+
// Step 2: Enable middleware types
23+
declare module "react-router" {
24+
interface Future {
25+
unstable_middleware: true; // 👈 Enable middleware types
26+
}
27+
}
28+
```
29+
30+
It was up to you to keep the runtime future flags synced with the types for those future flags.
31+
This was confusing and error-prone.
32+
33+
Now, React Router will automatically enable types for future flags.
34+
That means you only need to specify the runtime future flag:
35+
36+
```ts
37+
// react-router.config.ts
38+
39+
// Step 1: Enable middleware
40+
export default {
41+
future: {
42+
unstable_middleware: true,
43+
},
44+
};
45+
46+
// No step 2! That's it!
47+
```
48+
49+
Behind the scenes, React Router will generate the corresponding `declare module` into `.react-router/types`.
50+
Currently this is done in `.react-router/types/+register.ts` but this is an implementation detail that may change in the future.

packages/react-router-dev/typegen/index.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,23 @@ export async function watch(
3131
await writeAll(ctx);
3232
logger?.info(pc.green("generated types"), { timestamp: true, clear: true });
3333

34-
ctx.configLoader.onChange(async ({ result, routeConfigChanged }) => {
35-
if (!result.ok) {
36-
logger?.error(pc.red(result.error), { timestamp: true, clear: true });
37-
return;
38-
}
34+
ctx.configLoader.onChange(
35+
async ({ result, configChanged, routeConfigChanged }) => {
36+
if (!result.ok) {
37+
logger?.error(pc.red(result.error), { timestamp: true, clear: true });
38+
return;
39+
}
3940

40-
ctx.config = result.value;
41-
if (routeConfigChanged) {
42-
await writeAll(ctx);
43-
logger?.info(pc.green("regenerated types"), {
44-
timestamp: true,
45-
clear: true,
46-
});
41+
ctx.config = result.value;
42+
if (configChanged || routeConfigChanged) {
43+
await writeAll(ctx);
44+
logger?.info(pc.green("regenerated types"), {
45+
timestamp: true,
46+
clear: true,
47+
});
48+
}
4749
}
48-
});
50+
);
4951

5052
return {
5153
close: async () => await ctx.configLoader.close(),
@@ -103,6 +105,10 @@ function register(ctx: Context) {
103105
interface Register {
104106
params: Params;
105107
}
108+
109+
interface Future {
110+
unstable_middleware: ${ctx.config.future.unstable_middleware}
111+
}
106112
}
107113
`;
108114

playground/middleware/react-router.config.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
import type { Config } from "@react-router/dev/config";
2-
import type { Future } from "react-router";
3-
4-
declare module "react-router" {
5-
interface Future {
6-
unstable_middleware: true;
7-
}
8-
}
92

103
export default {
114
future: {

0 commit comments

Comments
 (0)