Background
The UI test suite has 14 spots (after #2776) that mock TanStack Query / TanStack Mutation hooks with the partial-cast pattern:
```ts
useFooMock.mockReturnValue({
data: [],
isLoading: false,
} as unknown as ReturnType)
```
This pattern silences the structural type check — the mock only fills in what the test under test actually reads. It's been in the codebase for a while and is the established convention.
The trade-off
Why the cast is fine in practice: keeps tests focused on what they actually exercise; one-line additions per call site.
Why it's a smell: if the upstream type adds a required field (TanStack Query bumps, contract changes), the cast hides the drift. Tests still compile, still pass green, but no longer prove the mock matches reality.
What "fixing it properly" would look like
Add small typed helpers under `apps/ui/src/test-utils/` (new dir), e.g.:
```ts
export const buildUseQueryResult = (
overrides: Partial<UseQueryResult>,
): UseQueryResult => ({
// sane defaults for all 28+ properties
...defaults,
...overrides,
})
```
Then call sites become:
```ts
useFooMock.mockReturnValue(buildUseQueryResult({ data: [], isLoading: false }))
```
— compile-time-validated, no double-cast, real contract.
Scope (when picked up)
- Inventory all current sites: `grep -rn 'as unknown as ReturnType<typeof use' apps/ui/src --include='.spec.'`
- Add helpers for each affected hook return type (UseQueryResult, UseMutationResult, QueryClient, hook-specific shapes).
- Migrate all sites in one PR for consistency.
- Document the pattern in the test-utils README.
Why not in #2776
That PR's job is to unblock tsc and stop CI from silently passing. Refactoring 14 call sites + introducing a new helper convention is a separate decision.
Background
The UI test suite has 14 spots (after #2776) that mock TanStack Query / TanStack Mutation hooks with the partial-cast pattern:
```ts
useFooMock.mockReturnValue({
data: [],
isLoading: false,
} as unknown as ReturnType)
```
This pattern silences the structural type check — the mock only fills in what the test under test actually reads. It's been in the codebase for a while and is the established convention.
The trade-off
Why the cast is fine in practice: keeps tests focused on what they actually exercise; one-line additions per call site.
Why it's a smell: if the upstream type adds a required field (TanStack Query bumps, contract changes), the cast hides the drift. Tests still compile, still pass green, but no longer prove the mock matches reality.
What "fixing it properly" would look like
Add small typed helpers under `apps/ui/src/test-utils/` (new dir), e.g.:
```ts
export const buildUseQueryResult = (
overrides: Partial<UseQueryResult>,
): UseQueryResult => ({
// sane defaults for all 28+ properties
...defaults,
...overrides,
})
```
Then call sites become:
```ts
useFooMock.mockReturnValue(buildUseQueryResult({ data: [], isLoading: false }))
```
— compile-time-validated, no double-cast, real contract.
Scope (when picked up)
Why not in #2776
That PR's job is to unblock tsc and stop CI from silently passing. Refactoring 14 call sites + introducing a new helper convention is a separate decision.