Тип тестирования параметра функции - PullRequest
3 голосов
/ 07 июля 2019

У меня есть такая функция:

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.slug и fields.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 {};
};

1 Ответ

2 голосов
/ 07 июля 2019

Да, вы можете - использовать утверждение типа :

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