Home > Net >  Having difficulty understanding the use of Type predicate in Typescript
Having difficulty understanding the use of Type predicate in Typescript

Time:09-20

I am new to TypeScript and was reading about Type Narrowing and Type Guards. I came across the following code where the typescript compiler shows an error and the author solves it using type predicates. https://dev.to/smeijer/typescript-type-guards-and-type-predicates-4m5e For example,

type Article = {
  frontMatter: Record<string, unknown>;
  content: string;
}

type NotFound = { 
  notFound: true;
}

type Page = Article | NotFound;

function handleRequest(slug: string): string {
  const article = db.articles.findOne({ slug });
  const page = article ?? { notFound: true };
  return render(page);
}

function render(page: Page) {
  if (page.content) { -------> Typescript showing Error
    return page.content; -----> Typescript showing Error
  }

  return '404 — not found';
}

As you can see, inside the render function, typescript compiler showing error saying that

Property 'content' does not exist on type 'Page'.
  Property 'content' does not exist on type 'NotFound'

My question is, inside the if block, I already know the content exists as a property of page, then why it is showing error and why using predicate solves the issue like following.

function isArticle(page: Page): page is Article {
  return typeof (page as Article).content !== 'undefined';
}

function render(page: Page) {
  if (isArticle(page)) {
    return page.content;
  }

  return '404 — not found';
}

Thanks in advance for your help.

CodePudding user response:

if (page.content) { -------> Typescript showing Error

Typescript is set up to not let you access properties unless they definitely exist. So, as you know, this line is an error.

My question is, inside the if block, I already know the content exists as a property of page, then why it is showing error and why using predicate solves the issue like following.

You may know that, but typescript does not. When typescript encountered the error on the first line, it aborted any logic to try to narrow down the types. Typescript is basically waiting for you to fix the error. Until you do, typescript will not narrow the type, which means page is viewed as a Article | NotFound, and thus it's still illegal to access page.content.

The custom type guard you wrote is one possible way to fix the error, but you could also check whether page.content exists without accessing it, via the in operator:

if ('content' in page) {
  • Related