stripe-node icon indicating copy to clipboard operation
stripe-node copied to clipboard

Specify event.data.object as an alternative

Open merlinnot opened this issue 5 years ago • 9 comments
trafficstars

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

merlinnot avatar Jan 10 '20 08:01 merlinnot

Thanks for highlighting, @merlinnot. We're going to look into this.

cjavilla-stripe avatar Jan 10 '20 17:01 cjavilla-stripe

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.

rattrayalex-stripe avatar Jan 30 '20 00:01 rattrayalex-stripe

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

image

JamieS1211 avatar Feb 10 '20 03:02 JamieS1211

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.

JustinTRoss avatar Jun 20 '20 01:06 JustinTRoss

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.

svallory avatar Aug 11 '20 18:08 svallory

Strongly related: #1387

saiichihashimoto avatar Apr 20 '22 20:04 saiichihashimoto

@JamieS1211's solution to this is perfect, would be awesome to see this in de SDK itself!

ItsWendell avatar Jul 27 '22 10:07 ItsWendell

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:

Jule- avatar Aug 01 '22 19:08 Jule-

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

kgajera avatar Aug 27 '22 21:08 kgajera

Any updates from Stripe team about this?

patilanz avatar Jan 10 '23 17:01 patilanz

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.

JefferyHus avatar Mar 29 '23 20:03 JefferyHus

[> 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.

](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

hhsissi avatar Jul 13 '23 22:07 hhsissi

I think #1921 solves this issue!

huw avatar Oct 16 '23 23:10 huw

This is now available starting with v13.11.0

pakrym-stripe avatar Oct 26 '23 16:10 pakrym-stripe

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>

hayksaryan avatar Dec 21 '23 11:12 hayksaryan

Good point, apologies that we missed previous attributes. Filed https://github.com/stripe/stripe-node/issues/1978

pakrym-stripe avatar Dec 21 '23 17:12 pakrym-stripe

Good point, apologies that we missed previous attributes. Filed #1978

Thanks!

hayksaryan avatar Dec 22 '23 13:12 hayksaryan