Skip to content

Commit 8e98fae

Browse files
emmaling27benjavicente
authored and
Convex, Inc.
committedMar 3, 2025·
convex-backend PR 51: Add second workaround to circular type inference (#34901)
I added a second option to solve the circular type inference in actions: typing the handler function return type. It might be simpler than typing `runQuery` and `runMutation`, specially when there are multiple queries and mutations, so I place it first. I also made the title an h3, to be visible in the TOC, and because I think it is more of a problem of the action constructor been part of the type generation than the context. Maybe it need to be part of another page (I don't known witch could be), because this could also happen on other functions, like mutations with partial rollback 🤔 Co-authored-by: Benjamín Vicente <[email protected]> GitOrigin-RevId: 1e3981bfd62823d5d70bc0ef3c87a2968bfc323b

File tree

4 files changed

+36
-12
lines changed

4 files changed

+36
-12
lines changed
 

Diff for: ‎npm-packages/docs/docs/functions/actions.mdx

+20-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import Context from "!!raw-loader!@site/../private-demos/snippets/convex/actions
99
import ContextRunQuery from "!!raw-loader!@site/../private-demos/snippets/convex/myFunctions.ts";
1010
import ContextRunMutation from "!!raw-loader!@site/../private-demos/snippets/convex/actionsContextRunMutation.ts";
1111
import CircularError from "!!raw-loader!@site/../private-demos/snippets/convex/actionsCircularError.ts";
12-
import CircularErrorFixed from "!!raw-loader!@site/../private-demos/snippets/convex/actionsCircularErrorFixed.ts";
12+
import CircularErrorFixedResults from "!!raw-loader!@site/../private-demos/snippets/convex/actionsCircularErrorFixedResults.ts";
13+
import CircularErrorFixedReturn from "!!raw-loader!@site/../private-demos/snippets/convex/actionsCircularErrorFixedReturn.ts";
1314
import NPM from "!!raw-loader!@site/../private-demos/snippets/convex/actionsNPM.ts";
1415
import Node from "!!raw-loader!@site/../private-demos/snippets/convex/actionsNode.ts";
1516
import Call from "!!raw-loader!@site/../private-demos/snippets/src/actionsCall.tsx";
@@ -109,7 +110,7 @@ do:
109110
- To search a vector index, use the `vectorSearch` field. Read on about
110111
[Vector Search](/docs/search/vector-search.mdx).
111112

112-
#### Dealing with circular type inference
113+
### Dealing with circular type inference
113114

114115
<Details summary={<>
115116
Working around the TypeScript error: some action <code>implicitly has
@@ -127,14 +128,23 @@ infer the return type of the action. This is a minimal example of the issue:
127128
snippet="tsError"
128129
/>
129130

130-
To work around this, you should store the result of the `ctx.runQuery` or
131-
`ctx.runMutation` call in a variable with a type annotation:
132-
133-
<Snippet
134-
title="convex/myFunctions.ts"
135-
source={CircularErrorFixed}
136-
snippet="fixed"
137-
/>
131+
To work around this, there are two options:
132+
133+
1. Type the return value of the handler function explicitly:
134+
<Snippet
135+
title="convex/myFunctions.ts"
136+
source={CircularErrorFixedReturn}
137+
snippet="fixed"
138+
highlightPatterns={["null"]}
139+
/>
140+
2. Type the the result of the `ctx.runQuery` or `ctx.runMutation` call
141+
explicitly:
142+
<Snippet
143+
title="convex/myFunctions.ts"
144+
source={CircularErrorFixedResults}
145+
snippet="fixed"
146+
highlightPatterns={["null"]}
147+
/>
138148

139149
TypeScript will check that the type annotation matches what the called query or
140150
mutation returns, so you don't lose any type safety.

Diff for: ‎npm-packages/private-demos/snippets/convex/_generated/api.d.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import type {
1515
} from "convex/server";
1616
import type * as actionsArgsWithValidation from "../actionsArgsWithValidation.js";
1717
import type * as actionsCircularError from "../actionsCircularError.js";
18-
import type * as actionsCircularErrorFixed from "../actionsCircularErrorFixed.js";
18+
import type * as actionsCircularErrorFixedResults from "../actionsCircularErrorFixedResults.js";
19+
import type * as actionsCircularErrorFixedReturn from "../actionsCircularErrorFixedReturn.js";
1920
import type * as actionsConstructor from "../actionsConstructor.js";
2021
import type * as actionsContext from "../actionsContext.js";
2122
import type * as actionsContextRunMutation from "../actionsContextRunMutation.js";
@@ -110,7 +111,8 @@ import type * as writingDataReplace from "../writingDataReplace.js";
110111
declare const fullApi: ApiFromModules<{
111112
actionsArgsWithValidation: typeof actionsArgsWithValidation;
112113
actionsCircularError: typeof actionsCircularError;
113-
actionsCircularErrorFixed: typeof actionsCircularErrorFixed;
114+
actionsCircularErrorFixedResults: typeof actionsCircularErrorFixedResults;
115+
actionsCircularErrorFixedReturn: typeof actionsCircularErrorFixedReturn;
114116
actionsConstructor: typeof actionsConstructor;
115117
actionsContext: typeof actionsContext;
116118
actionsContextRunMutation: typeof actionsContextRunMutation;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { api } from "./_generated/api";
2+
import { action } from "./_generated/server";
3+
4+
// @snippet start fixed
5+
export const myAction = action({
6+
args: {},
7+
handler: async (ctx): Promise<null> => {
8+
const result = await ctx.runQuery(api.myFunctions.getSomething);
9+
return result;
10+
},
11+
});
12+
// @snippet end fixed

0 commit comments

Comments
 (0)
Please sign in to comment.