首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在筛选对象数组时,用于可选属性的TypeGuards

在筛选对象数组时,用于可选属性的TypeGuards
EN

Stack Overflow用户
提问于 2022-05-18 15:52:11
回答 1查看 288关注 0票数 0

我在类型记录中有以下接口:

代码语言:javascript
复制
interface ComplexRating {
  ratingAttribute1?: number;
  ratingAttribute2?: number;
  ratingAttribute3?: number;
  ratingAttribute4?: number;
}

export interface Review {
  rating: ComplexRating | number;
}

为了简单起见,我想计算一下ratingAttribute1的平均评分。

因此,鉴于这些审查:

代码语言:javascript
复制
const reviews: Review[] = [
  { rating: { ratingAttribute1: 5 } },
  { rating: { ratingAttribute1: 10 } },
  { rating: { ratingAttribute2: 15 } },
  { rating: 5 }
]

我可以过滤掉那些我感兴趣的评论,比如:

代码语言:javascript
复制
const calculateAverageRating = (reviews: Review[]): number => {
  const reviewsWithRating = reviews.filter(
    (review) =>
      typeof review.rating === 'object' &&
      typeof review.rating['ratingAttribute1'] === 'number'
  );
  return (
    reviewsWithRating.reduce((acc, review) => {
      let newValue = acc;
      if (typeof review.rating === 'object') {
        const rating = review.rating['ratingAttribute1'];
        if (rating) {
          newValue += rating;
        }
      }
      return newValue;
    }, 0.0) / reviewsWithRating.length
  );
};

现在,令人烦恼的是,类型记录不知道通过运行reviews.filter函数,我输入的Review只保护了具有rating of type ComplexType的Review的子集,还有那些具有ratingAttribute1: number;而不是ratingAttribute?: number的评论。

我想要结束的是不必重复计算中的类型检查,有效地结束如下:

代码语言:javascript
复制
const calculateAverageRating = (reviews: Review[]): number => {
  const reviewsWithRating = reviews.filter(
    (review) =>
      typeof review.rating === 'object' &&
      typeof review.rating['ratingAttribute1'] === 'number'
  );
  return (
    reviewsWithRating.reduce(
      (acc, review) => acc + review.rating['ratingAttribute1'],
      0.0
    ) / reviewsWithRating.length
  );
};

但这是不可能的:

有什么方法可以达到这个级别的类型保护吗?还是有一种更整洁的方式来做这种事?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-18 16:02:31

.filter()函数将始终返回与参数相同类型的数组。这就是为什么reviewsWithRating仍然是一个Review[]的原因,即使在您过滤它之后。

要改变这一点,可以在回调中添加一个型保护

代码语言:javascript
复制
const reviewsWithRating = reviews.filter(
  (review): review is { rating: Required<ComplexRating> } =>
    typeof review.rating === 'object' &&
    typeof review.rating['ratingAttribute1'] === 'number'
);

现在,TypeScript将知道reviewsWithRating{ rating: Required<ComplexRating> }[]类型的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72292351

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档