Brandon McConnell
Brandon McConnell

Reputation: 6119

Boolean truthiness narrowing not working in Typescript

I've checked similar questions and cannot find any examples like mine. I am using a function to narrow down a boolean option in an if/else clause, but it only works when defined explicitly, not using the function.

Here is the code I am working with—

TYPES

type SimpleCellContent = string | number;
type ComplexCellContent = {
  content: SimpleCellContent;
  formatter: (content: any) => string;
  class?: string;
  link?: string;
  linkClass?: string;
};
type CellContent = SimpleCellContent | ComplexCellContent;

LOGIC

const isSimpleContent = (cellData: CellContent) => {
  return typeof cellData === 'string' || typeof cellData === 'number' || typeof cellData === 'undefined';
};

const extractContent = (cellData: CellContent) => {
  if (isSimpleContent(cellData)) {
    return cellData;
  } else if (typeof cellData.content !== 'undefined') { // <---  ERROR !!! 🚨
    return cellData.content;
  } else {
    throw new Error('Invalid cell data: ' + JSON.stringify(cellData));
  }
};

The error reads…

Property 'content' does not exist on type 'CellContent'.
  Property 'content' does not exist on type 'string'. ts(2339)

However, if I switch isSimpleContent(cellData) to be the exact same return value of the previous function (typeof cellData === 'string' || typeof cellData === 'number' || typeof cellData === 'undefined'), it works without an issue.

Why wouldn't this work the same way when using a function?

Upvotes: 1

Views: 431

Answers (1)

Bal&#225;zs &#201;des
Bal&#225;zs &#201;des

Reputation: 13807

Unless there are new developments in the language, a function only becomes a type guard, if you explicitly mark it in the return type:

const isSimpleContent = (cellData: CellContent): cellData is SimpleCellContent => {
  return typeof cellData === 'string' || typeof cellData === 'number' || typeof cellData === 'undefined';
};

Docs: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates

Upvotes: 4

Related Questions