TanStackT
TanStack•4w ago•
12 replies
uncertain-scarlet

Stripe 20.0.0 Serialization with latest tanstack start

Hey šŸ‘‹

After upgrading to stripe@20.0.0, I’m running into a TypeScript type error when returning a Stripe subscription from a TanStack Start server function.

Stack

@tanstack/start / @tanstack/react-start: 1.139.x

stripe: 20.0.0

typescript: 5.x

Runtime: Node 20

I have a server function roughly like this:
import { createServerFn } from '@tanstack/react-start';
import { db } from '@repo/db';
import { stripeClient } from '../stripe';
import type Stripe from 'stripe';

type StripePrice = {
  // my internal metadata shape
  recurrence: 'month' | 'year';
  productId: string;
  description: string;
  priceId: string;
  costPerCredit: number;
  // ...
};

export const getSubscription = createServerFn()
  // inputValidator + middleware omitted for brevity
  .handler(async ({ context: { db, session } }) => {
    const sub = await db.query.subscriptions.findFirst({
      where: (subs, { eq }) =>
        eq(subs.referenceId, session.session.userId),
    });

    if (!sub?.stripeSubscriptionId) return null;

    const stripeSub: Stripe.Response<Stripe.Subscription> =
      await stripeClient.subscriptions.retrieve(
        sub.stripeSubscriptionId,
        {
          expand: [
            'latest_invoice',
            'latest_invoice.payment_intent',
            'latest_invoice.charge',
            'latest_invoice.payment_intent.payment_method',
            'items.data.price.product',
            'schedule',
          ],
        },
      );

    return {
      ...sub,
      // previously compatible
      metadata: sub.metadata as StripePrice | undefined,
      // this is what triggers the type error now
      stripe: stripeSub,
    };
  });


The error I see (shortened) looks like:

Type 'Promise<{ metadata: StripePrice | undefined; stripe: Stripe.Response<Stripe.Subscription>; ... } | null>'
is not assignable to type 'Promise<{ metadata: { ...my custom shape... } | undefined; ... } | null>'.

The types of 'stripe.automatic_tax.liability' are incompatible between these types.
Type 'Liability | null' is not assignable to type '{ account?: string | { ... } | undefined; type: Type; } | null'.
...


It drills all the way down into Stripe’s complex nested types (automatic_tax.liability.account, external_accounts, etc.) and complains that my handler return type doesn’t match the expected result type inferred for the server function / Register.

A few notes:

This was compiling fine before upgrading to stripe@20.0.0 & ^1.12 start.

The runtime behavior is fine if I bypass types (e.g. stripe: stripeSub as any), so it seems purely a typing / inference issue.

Questions

Is there a recommended pattern in TanStack Start for returning 3rd-party SDK responses like Stripe.Response<Stripe.Subscription> from server functions?

e.g. should I always expose them as unknown / Record<string, unknown> in my Register / result types and cast on the client?

Is there any change in how Start infers / constrains the server function result type that might make Stripe v20’s updated types incompatible now?

I’m happy to put together a minimal repro if that helps, but wanted to sanity-check first if there’s a known ā€œdon’t return SDK types directly from server functionsā€ guideline or an example for Stripe v20.

Thanks!
Was this page helpful?