TanStack / TanStack/ai

UseGenerationReturn discards TInput: `generate` is typed `(input: Record<string, any>)`

Open
#1,003 1 comment 0 reactions 1 assignee View on GitHub

@AlemTuzlak is already working on this.

Since Aug 21, 2026.

waiting-on: maintainer
Dominant language
TypeScript
Stars
3.1k
Forks
331
Avg merge
1d 22h
Merged PRs (30d)
160

Description

Found while reviewing the @tanstack/ai-octane port (#1000). Fixed there; filing so the other adapters can catch up.

Problem

useGeneration takes a TInput extends Record<string, any> type parameter, and its internal generate really is (input: TInput) => Promise<void>. But the exported return type throws that away:

export interface UseGenerationReturn<TOutput> {
  generate: (input: Record<string, any>) => Promise<void>
  // ...
}

and the implementation casts to match:

return {
  generate: generate as (input: Record<string, any>) => Promise<void>,
  // ...
}

So required and narrow input fields are unchecked at the call site. With useGeneration<{ prompt: string; steps: number }, R>, all of these compile:

generate({ prompt: 'x' })                      // missing `steps`
generate({ prompt: 'x', steps: 'four' })       // wrong type
generate({ prompt: 'x', steps: 4, seed: 1 })   // unknown key

Fix

Parameterize the return type with TInput and drop the cast:

-export interface UseGenerationReturn<TOutput> {
-  generate: (input: Record<string, any>) => Promise<void>
+export interface UseGenerationReturn<TInput, TOutput> {
+  generate: (input: TInput) => Promise<void>
-): UseGenerationReturn<InferGenerationOutputFromReturn<TResult, TTransformed>> {
+): UseGenerationReturn<
+  TInput,
+  InferGenerationOutputFromReturn<TResult, TTransformed>
+> {
 return {
-  generate: generate as (input: Record<string, any>) => Promise<void>,
+  generate,

In ai-octane this needed no other changes — the media hooks (useGenerateImage/Audio/Speech/Video) declare their own return types and don't reference UseGenerationReturn.

Caveat

This changes the arity of an exported type, so it's breaking for anyone who writes UseGenerationReturn<T> explicitly. Worth batching into a release that's already taking a version bump. ai-octane could absorb it freely (unpublished at 0.0.0), which is why it diverges today — see packages/ai-octane/status.json.

Test

packages/ai-octane/typetests/use-generation.test-d.ts locks this in with @ts-expect-error cases for each of the three bad calls above; verified to fail if the widening is reintroduced.

Affected

  • @tanstack/ai-react
  • @tanstack/ai-vue
  • @tanstack/ai-solid

(@tanstack/ai-octane fixed in #1000.)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.