Home > Mobile >  Is there a TS configuration parameter I'm missing to force a type from a union?
Is there a TS configuration parameter I'm missing to force a type from a union?

Time:07-13

I have a problem with the Stripe Node.js API (apiVersion '2020-08-27' - which as of 2022-07-21 is current).

The customers.retrieve method returns a response of type Promise<Stripe.Response<Stripe.Customer | Stripe.DeletedCustomer>>.

According to the documentation, and a Github thread here: Use discriminated unions to easier make distinciton between types, if the response from customers.retrieve has property deleted = true, then the type should be DeletedCustomer, and otherwise should be Customer.

The link above indicates that it is sufficient to check the deleted property as below, and then TypeScript should be able to discern that the response represents a Customer instead of a DeletedCustomer.

let customer = await this.stripe.customers.retrieve(customerId, { expand: ['subscriptions'] })
if (!customer.deleted) {
  const subscriptions = customer.subscriptions[0]
}

However, none of the properties of Customer are available within the conditional block as expected.

I have a solution that seems to do what I need - but it doesn't seem "by the book", and I wish that I could figure out if TypeScript can fix this issue for me. Here is my solution:

if (customer.deleted) return
customer = <Stripe.Response<Stripe.Customer>>customer
const subscription = customer.subscriptions[0]

Edit to add: I should add that this is a Nest.js project.

CodePudding user response:

I'm seeing this work fine with typescript 4.4.4.

See codesandbox link here

import { Stripe } from "stripe";

const stripe = new Stripe("x", { apiVersion: "2020-08-27" });

const fn = async () => {
  const customer = await stripe.customers.retrieve("x", {
    expand: ["subscriptions"]
  });
  if (!customer.deleted) {
    console.log(customer); // customer here resolves to Stripe.Customer & { ... }
    const subscriptions = customer.subscriptions;
    const subscription = subscriptions && subscriptions.data[0]; // note that this is slightly different from your code
  } else {
    console.log(customer); // customer here resolves to Stripe.DeletedCustomer & { ... }
  }
};


CodePudding user response:

The problem config option is: "strictNullChecks": false, and the lack of strict: true in the tsconfig.

The default of strictNullChecks is true if strict, false otherwise. https://www.typescriptlang.org/tsconfig#strictNullChecks

Thus, "strict": true must be used to fix this issue.

  • Related