Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing type of function parameter

I have a function like so:

type Entry = PageBasic | PageHome | PostCollection | PostProduct;

export default (entry: Entry): Params => {
  const contentType = entry.sys.contentType.sys.id;

  if (contentType ==='pageBasic') {
    return { slug: entry.fields.slug };
  }

  if (contentType === 'pageCollection') {
    return { collection: entry.fields.slug };
  }

  if (contentType === 'postProduct') return {
    collection: entry.fields.collection.fields.slug,
    product: entry.fields.slug,
  };

  return {};
};

My types for PageBasic, PostCollection and PostProduct are all different. Some have the fields.slug and fields.collection data and some don't. My if statements confirm to me which entry type I'm dealing with e.g. if the contentType === 'pageCollection' then I'm dealing with PostCollection type. However Typescript doesn't know that. Is there a way for me to tell it if my condition is true, then the type of the entry param is PostCollection or something?

The only other way I know to do this is adding lots more conditional statements to check if the keys exist, which seems pointless when I already know they will based on my conditional statements. e.g:

export default (entry: Entry): Params => {
  const contentType = entry.sys.contentType.sys.id;

  if (contentType === CT_PAGE_BASIC) {
    if ('slug' in entry.fields) return { slug: entry.fields.slug };
  }

  if (contentType === CT_POST_COLLECTION) {
    if ('slug' in entry.fields) return { collection: entry.fields.slug };
  }

  if (contentType === CT_POST_PRODUCT) return {
    ...'collection' in entry.fields && { collection: entry.fields.collection.fields.slug },
    ...'slug' in entry.fields && { product: entry.fields.slug },
  };

  return {};
};
like image 442
CaribouCode Avatar asked Jul 22 '26 06:07

CaribouCode


1 Answers

Yes you can - use a type assertion:

if (contentType ==='pageBasic') {
  return { slug: <PageBasic>(entry).fields.slug };
}

You could also return an object with conditionals:

export default (entry: Entry): Params => {
  const contentType = entry.sys.contentType.sys.id;
  return { 
    ...(contentType ==='pageBasic' ? { slug: (<PageBasic>entry).fields.slug } : 0),
    ...(contentType === 'pageCollection' ? { collection: (<PostCollection>entry).fields.slug } : 0),
    ...(contentType === 'postProduct' ? { collection: (<PostProduct>entry).fields.collection.fields.slug, product: (<PostProduct>entry).fields.slug } : 0)
  };
};
like image 102
Jack Bashford Avatar answered Jul 23 '26 18:07

Jack Bashford