【问题标题】:Testing type of function parameter测试功能参数类型
【发布时间】:2019-11-17 04:32:14
【问题描述】:

我有这样的功能:

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 {};
};

我的 PageBasic、PostCollection 和 PostProduct 类型都不同。有些有 fields.slugfields.collection 数据,有些没有。我的 if 语句向我确认了我正在处理的条目类型,例如如果是contentType === 'pageCollection',那么我正在处理PostCollection 类型。但是 Typescript 不知道这一点。有没有办法告诉它如果我的条件为真,那么入口参数的类型是 PostCollection 什么的?

我知道的唯一其他方法是添加更多条件语句来检查键是否存在,当我已经知道它们会基于我的条件语句时,这似乎毫无意义。例如:

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 {};
};

【问题讨论】:

  • return {slug: (<PageBasic>entry.fields).slug }; 有什么问题?
  • ^^ 更积极地说:-)type assertion 怎么样? return {slug: (<PageBasic>entry).fields.slug };return {slug: (entry as PageBasic).fields.slug };
  • 此解决方案会引发 Typescript 错误:Property 'slug' does not exist on type 'PageBasic. 即使 PageBasic 上确实存在 slug。
  • 啊,我想这只是括号的位置。现在一切正常(见 Jack Bashford 的回答)。
  • 如果您提供minimal reproducible example,我们可能会为您提供更好的帮助,将其减少为(比如说)两种类型并提供完整的示例。综上所述,我怀疑我们可以避免类型断言。

标签: javascript typescript object ecmascript-6


【解决方案1】:

是的,你可以 - 使用 type assertion:

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

你也可以返回一个带有条件的对象:

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)
  };
};

【讨论】:

  • 太棒了,这是一种享受。我的 linting 希望我将其写为 return { slug: (entry as PageBasic).fields.slug };,但它按预期工作。谢谢!
  • 没问题@Coop,总是乐于提供帮助。我还在我的答案中添加了另一部分,可能会解决您的条件问题。
猜你喜欢
  • 2022-01-24
  • 2021-09-25
  • 2019-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多