Typescript: Checking disjoint union with extra null-checks

50 views Asked by At

I'm using a disjoint union to represent different states a payment can be in our typescript codebase. So I assert it's type first with an if in order to access it's properties, but when I check multiple states together alongside some null-checking condition, the compiler gets angry at me and I can't tell the reason.

type Payment = {
  tag: "Pending",
  link: string;
} | {
  tag: "Expired",
  link: string | null;
} | {
  tag: "Other"
};

function test(payment: Payment): string {
  if (payment.tag === "Pending" || (payment.tag === "Expired" && payment.link !== null)) {
    // This fails with:
    // Type 'string | null' is not assignable to type 'string'.
    return payment.link;
  }

  return "this has no link";
}

A simple solution is checking these conditions separately:

// This is fine now
function test(payment: Payment): string {
  if (payment.tag === "Pending") {
    return payment.link;
  }

  if (payment.tag === "Expired" && payment.link !== null) {
    return payment.link;
  }

  return "this has no link";
}

But I don't want to have to copy-paste the code in two separate ifs. Why can't typescript handle this simple case of null-checking? Am I doing something wrong?

1

There are 1 answers

0
Julio Di Egidio -- inactive On BEST ANSWER

Apparently the TS compiler is just not that smart.

This solution moving around parentheses works:

  if ((payment.tag === "Pending" || payment.tag === "Expired") && payment.link !== null) {
    return payment.link;
  }

which in turn here can be simplified to:

  if (payment.tag !== "Other" && payment.link !== null) {
    return payment.link;
  }