stripe-node
stripe-node copied to clipboard
Specify event.data.object as an alternative
event.data.object is currently specified as an empty interface, which seems invalid. My understanding of the API is that it should be an alternative of all possibilities. Relevant code:
https://github.com/stripe/stripe-node/blob/b2d32ef3a987b3c740bbc44c99a8209a92c3a5ee/types/2019-12-03/Events.d.ts#L56-L66
Thanks for highlighting, @merlinnot. We're going to look into this.
In the meantime, we recommend casting, as in this example: https://github.com/stripe/stripe-node/master/8f3c3ec/examples/webhook-signing/typescript-node-express/express-ts.ts#L58-L60
const charge = event.data.object as Stripe.Charge;
In the future, we hope to type events well enough that checking event.type === 'charge.succeeded' will be enough for TS to infer that event.data.object is a Stripe.Charge.
In reality this "data.object" value is one of ~49 different object types that can be returned via a webhook event. You will also notice that "type" is defined simply as a "string". In reality the type is one of ~151 different distinct strings.
If the "Stripe.Event" type was instead created via a union type of the ~49 different event types (based on the type of object returned), with each event type having a typing for the "type" key as a literal string union of all the relevant event events this should do the trick. I have actually gone through this process manually and created a d.ts file that will give "Stripe.DiscriminatedEvent" type that you can cast to and then discriminate with - I will put the link below. Please see attached image as an example below. I hope this helps anyone here as a or if it is of any use to update the typings.
https://github.com/JamieS1211/StripeDiscriminatedEventTyping/blob/master/StripeDiscriminatedEvents.d.ts

Also worth noting, at a minimum, it would be helpful to add an [index: string]: any to Data.Object interface. At present, you receive an error if you attempt to check event.data.object.\<anything\>, as it is strictly typed to an empty object.
There's a quick workaround for this. Add this to a declaration or any ts file imported in your project:
declare module 'stripe' {
namespace Stripe {
interface TypedEventData<T> extends Stripe.Event.Data {
object: T;
previous_attributes?: Partial<T>;
}
interface TypedEvent<T = any> extends Stripe.Event {
data: TypedEventData<T>;
type: Exclude<Stripe.WebhookEndpointCreateParams.EnabledEvent, '*'>;
}
}
}
Then use Stripe.TypedEvent<Stripe.Subscription> for example. This could easily be added to Stripe's official typing too.
Strongly related: #1387
@JamieS1211's solution to this is perfect, would be awesome to see this in de SDK itself!
2 years later still no real out-of-the-box solution for typing? :eyes:
@JamieS1211 do you have an updated version of your type def file? Thanks a lot! :pray:
In the meantime while we don't have official typings, I published a package that contains the typings: https://github.com/kgajera/stripe-event-types
The typings are generated by scraping Stripe's docs that list the types of events: https://stripe.com/docs/api/events/types
Or if you just want to copy the type declarations, they are here: https://github.com/kgajera/stripe-event-types/blob/main/index.d.ts
Any updates from Stripe team about this?
This does not stop only on casting or using some provided solutions here, it goes deep as well into the expected object type. There are many missing properties from objects, for example the events customer.subscription.* return an object that contains a plan property, but it is not the case for Stripe.Subscription. stripe.webhooks.constructEvent is returning a flat type of Stripe.Event so it is really a nightmare to type it, casting is something I would love to stay away from as much as possible.
[> In the meantime, we recommend casting, as in this example: https://github.com/stripe/stripe-node/master/8f3c3ec/examples/webhook-signing/typescript-node-express/express-ts.ts#L58-L60
const charge = event.data.object as Stripe.Charge;In the future, we hope to type events well enough that checking
event.type === 'charge.succeeded'will be enough for TS to infer thatevent.data.objectis aStripe.Charge.
](https://github.com/stripe/stripe-node/issues/758#issuecomment-580027514)
Referenced link doesn't work anymore, here's an example =>
https://github.com/stripe/stripe-node/blob/master/examples/webhook-signing/express/main.ts#L57
I think #1921 solves this issue!
This is now available starting with v13.11.0
For me, event.data.previous_attributes is still typed as Stripe.Event.Data.PreviousAttributes.
I would expect a generic that properly infers Partial<Something> from Stripe.SomethingUpdatedEvent.
Otherwise, I'm forced to do it like this: event.data.previous_attributes as Partial<Stripe.Subscription>
Good point, apologies that we missed previous attributes. Filed https://github.com/stripe/stripe-node/issues/1978
Good point, apologies that we missed previous attributes. Filed #1978
Thanks!