Skip to content

[bugfix] #66 bug#70

Merged
js2me merged 4 commits intomasterfrom
fix/66/create-query-bug
Mar 16, 2026
Merged

[bugfix] #66 bug#70
js2me merged 4 commits intomasterfrom
fix/66/create-query-bug

Conversation

@js2me
Copy link
Copy Markdown
Owner

@js2me js2me commented Mar 16, 2026

Summary by CodeRabbit

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

This PR introduces type-safety improvements and test coverage for the mobx-tanstack-query library, including a bug fix for initial data handling in preset style (#66). Changes add comprehensive TypeScript typings tests, refactor the createQuery type layer with new utility types and overloads, update mutation types to use ESM module structure, enhance query tests with type compatibility checks, and document alternative packages.

Changes

Cohort / File(s) Summary
Release & Build Configuration
.changeset/tame-stars-exist.md, package.json, tsconfig.test.json
Added changeset documenting patch release for bug fix #66; introduced test:types script to check TypeScript against tsconfig.test.json; updated include/exclude patterns and added path mappings for modules.
Documentation
docs/introduction/getting-started.md
Added Alternatives section listing three external package options with documentation links.
Mutation Type Updates
src/mutation.test.ts
Updated imports to use .js ESM extensions; refactored MutationFn signature from variadic to (variables: TVariables, context: MutationFunctionContext) => any; removed @ts-expect-error directive.
Query Type System Refactoring
src/preset/create-query.ts, src/preset/create-query.test.ts
Introduced new utility types (QueryFnDataFromFn, QueryFnCallback, CreateQueryParamsFromFn variants, ValidateCreateQueryParamsFromFn); expanded createQuery overloads to support function-based, options-based, and queryClient-based invocation patterns; added initialData support as function or data value; comprehensive typing tests for overload validation and type inference preservation.
Query & Infinite Query Tests
src/query.test.ts, src/infinite-query.test.ts
Added type bug #66 test validating initialData/queryFn type compatibility; added refetchInterval typings tests for InfiniteQuery with page type preservation; tightened type annotations on query variables.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 Hops through types with care so bright,
Preset queries now compile just right,
Initial data plays its part,
Tests ensure we're sharp and smart,
The bugfix #66 sees the light!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title '[bugfix] #66 bug' is vague and lacks descriptive detail about the actual changes, using generic terms like 'bug' without specifying what bug was fixed. Replace with a more specific title describing the bug fix, such as '[bugfix] Fix initialData type validation in createQuery (#66)' or similar that clarifies what bug was addressed.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/66/create-query-bug
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/preset/create-query.ts (1)

262-284: ⚠️ Potential issue | 🟡 Minor

Fix incorrect reference to onInit callback parameter

The onInit property belongs to the options object (args[1]), not the query function (args[0]). Line 270 should be args[1]?.onInit?.(query) instead of args[0]?.onInit?.(query).

🐛 Fix
       onInit: (query) => {
         queryClient.mount();
-        args[0]?.onInit?.(query);
+        args[1]?.onInit?.(query);
       },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/preset/create-query.ts` around lines 262 - 284, The onInit callback is
being invoked on the wrong argument in createQuery: change the invocation from
args[0]?.onInit?.(query) to args[1]?.onInit?.(query) so the options object's
onInit is called; update the onInit handler inside the function branch that
constructs new Query with queryFn to call args[1]?.onInit?.(query) (keep the
existing queryClient.mount() call and other properties intact).
🧹 Nitpick comments (2)
src/infinite-query.test.ts (1)

487-493: Document the any workaround for refetchInterval.

The explicit query: any annotation suggests a type inference limitation. Consider adding a brief comment explaining why this workaround is needed (e.g., upstream @tanstack/query-core typing issue) to help future maintainers understand this is intentional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/infinite-query.test.ts` around lines 487 - 493, Add a brief inline
comment above the refetchInterval handler explaining why the parameter is typed
as any: note that this is an intentional workaround for a known upstream typing
limitation in `@tanstack/query-core` (link or issue number optional), so future
maintainers know the cast is deliberate; update the refetchInterval function
signature comment near the query parameter to mention the typing gap and that it
should be removed once upstream fixes their types.
src/query.test.ts (1)

3954-3956: Consider adding queryKey for completeness.

While valid for type-checking purposes, this test case omits queryKey. If the test file is ever executed at runtime (not just type-checked), this query would lack an essential property.

Suggested enhancement
     createQuery(() => 1, {
       initialData: 2,
+      queryKey: ['type-test-66'],
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/query.test.ts` around lines 3954 - 3956, The test call to createQuery(()
=> 1, { initialData: 2 }) omits the required runtime property queryKey; update
the createQuery invocation to include a unique queryKey (e.g., queryKey:
['test', 'simple'] or similar) alongside initialData so the query has the
essential identifier at runtime, ensuring createQuery and its options (queryKey,
initialData) are provided consistently in the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/preset/create-query.test.ts`:
- Around line 8-93: The test "preserves typings for overloads" creates live
queries that run at runtime; wrap the whole body of that it(...) callback in a
compile-only block (e.g. if (false) { ... }) so TypeScript still verifies types
but nothing executes, and apply the same change to the similar block at lines
128-139; locate usages of createQuery and new QueryClient() inside that test and
leave the existing `@ts-expect-error` comments intact so the type assertions
remain checked but no queries are created or run at runtime.

---

Outside diff comments:
In `@src/preset/create-query.ts`:
- Around line 262-284: The onInit callback is being invoked on the wrong
argument in createQuery: change the invocation from args[0]?.onInit?.(query) to
args[1]?.onInit?.(query) so the options object's onInit is called; update the
onInit handler inside the function branch that constructs new Query with queryFn
to call args[1]?.onInit?.(query) (keep the existing queryClient.mount() call and
other properties intact).

---

Nitpick comments:
In `@src/infinite-query.test.ts`:
- Around line 487-493: Add a brief inline comment above the refetchInterval
handler explaining why the parameter is typed as any: note that this is an
intentional workaround for a known upstream typing limitation in
`@tanstack/query-core` (link or issue number optional), so future maintainers know
the cast is deliberate; update the refetchInterval function signature comment
near the query parameter to mention the typing gap and that it should be removed
once upstream fixes their types.

In `@src/query.test.ts`:
- Around line 3954-3956: The test call to createQuery(() => 1, { initialData: 2
}) omits the required runtime property queryKey; update the createQuery
invocation to include a unique queryKey (e.g., queryKey: ['test', 'simple'] or
similar) alongside initialData so the query has the essential identifier at
runtime, ensuring createQuery and its options (queryKey, initialData) are
provided consistently in the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a08a22f7-ef36-4b6f-8b88-9b4daf3cf9cb

📥 Commits

Reviewing files that changed from the base of the PR and between 4753006 and 50d1bf0.

📒 Files selected for processing (9)
  • .changeset/tame-stars-exist.md
  • docs/introduction/getting-started.md
  • package.json
  • src/infinite-query.test.ts
  • src/mutation.test.ts
  • src/preset/create-query.test.ts
  • src/preset/create-query.ts
  • src/query.test.ts
  • tsconfig.test.json

Comment on lines +8 to +93
it('preserves typings for overloads', () => {
type User = {
id: string;
email: string;
};

const queryFnReturnsNumber: () => number = () => 1;
const getUser = async () => ({ id: '1', email: 'alice@example.com' });

const queryFromOptions = createQuery({
enabled: false,
queryKey: ['user'] as const,
queryFn: async () => ({ id: '1', email: 'alice@example.com' }),
});

expectTypeOf(queryFromOptions.data).toEqualTypeOf<User | undefined>();

const queryFromFnOnly = createQuery(async () => 1);

expectTypeOf(queryFromFnOnly.data).toEqualTypeOf<number | undefined>();

const queryFromFn = createQuery(
async () => ({ id: '1', email: 'alice@example.com' }),
{
enabled: false,
queryKey: ['user'] as const,
initialData: { id: '0', email: 'init@example.com' },
},
);

expectTypeOf(queryFromFn.data).toEqualTypeOf<User | undefined>();

const queryFromFnWithSelect = createQuery(getUser, {
enabled: false,
queryKey: ['user'] as const,
initialData: { id: '0', email: 'init@example.com' },
select: ((user) => user.email) satisfies (
user: Awaited<ReturnType<typeof getUser>>,
) => string,
});

expectTypeOf(queryFromFnWithSelect.data).toEqualTypeOf<
string | undefined
>();

const queryFromOptionsWithExplicitGenerics = createQuery<
number,
Error,
string
>({
enabled: false,
queryKey: ['count'] as const,
queryFn: async () => 1,
select: ((count) => count.toString()) satisfies (count: number) => string,
});

expectTypeOf(queryFromOptionsWithExplicitGenerics.data).toEqualTypeOf<
string | undefined
>();

const queryFromClientAndOptions = createQuery(new QueryClient(), () => ({
enabled: false,
queryKey: ['dynamic'] as const,
queryFn: async () => 1,
select: ((count) => count.toString()) satisfies (count: number) => string,
}));

expectTypeOf(queryFromClientAndOptions.data).toEqualTypeOf<
string | undefined
>();

createQuery(queryFnReturnsNumber, {
initialData: 2,
});

// @ts-expect-error initialData must match queryFn return type
createQuery(queryFnReturnsNumber, {
initialData: '2',
});

// @ts-expect-error initialData still uses queryFn data, not selected data
createQuery<User, Error, string, User, any[]>(getUser, {
initialData: 'alice@example.com',
select: (user) => user.email,
});
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don’t execute these type-coverage query creations as normal runtime tests.

These blocks instantiate several real queries, including intentionally mismatched initialData cases, but never dispose them. A few calls also leave enabled at its default, so they can fetch/update state and bleed into later tests. Please move this coverage to a non-executing type test, or skip these blocks; otherwise every query created here should be disabled and cleaned up.

💡 Minimal fix
-  it('preserves typings for overloads', () => {
+  it.skip('preserves typings for overloads', () => {
    // ...
   });

-  it('rejects mismatched initialData for queryFn overload', () => {
+  it.skip('rejects mismatched initialData for queryFn overload', () => {
    // ...
   });

Also applies to: 128-139

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/preset/create-query.test.ts` around lines 8 - 93, The test "preserves
typings for overloads" creates live queries that run at runtime; wrap the whole
body of that it(...) callback in a compile-only block (e.g. if (false) { ... })
so TypeScript still verifies types but nothing executes, and apply the same
change to the similar block at lines 128-139; locate usages of createQuery and
new QueryClient() inside that test and leave the existing `@ts-expect-error`
comments intact so the type assertions remain checked but no queries are created
or run at runtime.

@js2me js2me merged commit 1fa6988 into master Mar 16, 2026
6 checks passed
@github-actions github-actions bot mentioned this pull request Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant