TypeScript 类型缩小不适用于集合架构

问题描述 投票:0回答:1

我正在开发一个 Astro + TypeScript 项目,其中几乎没有具有特定模式的数据集合。

我使用 Zod 库来定义和构建每个数据集合,其简化方式如下所示:

import { defineCollection, z } from 'astro:content';

export const authorsCollection = defineCollection({
  schema: z.object({
    name: z.string(),
  }),
});

export const blogCollection = defineCollection({
  schema: z.object({
    title: z.string(),
    status: z.enum(['publish', 'trash', 'draft']).default('draft'),
  }),
});

export const collections = {
  authors: authorsCollection,
  blog: blogCollection,
};

我正在尝试编写一个辅助函数来根据集合的 ID 以不同方式处理集合(例如,能够根据博客文章中的状态字段过滤条目,而作者集合中没有该条目)。

这是我正在使用的功能:

import { getCollection } from 'astro:content';

import { collections as c } from '@content/config';

const collections = Object.keys (c);
type CollectionType = keyof (typeof c); // This solely translates to "authors" | "blog" string literal type.

type CollectionSettings = {
  status?: string[]; // Just for illustrative purposes.
};

export async function retrieveCollection (id: CollectionType, preferences = <CollectionSettings>{}) {
  const settings = Object.assign ({
    status: ['publish'], // Set default values.
  }, preferences);

  let entries = await getCollection (id); // Retrieve an initial list of content entries by its id.

  if (id === 'blog') { // This is where I distinguish whether or not the current request to the function belongs to a certain collection but the compiler doesn't seem to recognize it.
    entries = entries.filter (({ data: { status }}) => settings.status.includes (status)); // Here lies the error and the main reason for my current question.
  }

  // Perform another procedures such as filtering, searching fields, sorting entries by date, etc.

  return entries;
};

功能上我没有任何抱怨,因为一切都按其应有的方式进行;然而,编译器一直抱怨

Property 'status' does not exist on 'authorsCollection' type
,我希望能够修复它而不诉诸
@ts-ignore
指令。

问题似乎是 TypeScript 无法识别条件块中集合的特定类型。例如,在

if (id === 'blog')
块中,TypeScript 无法正确推断条目符合 BlogPost 架构,导致访问 status 属性(显然不存在)时出错。

我之前在这个网站上读过与

TypeScript type narrowing
相关的问题,用ChatGPT和GitHub Copilot检查过,没有结果。

所以我的问题是:

  1. 如何改进类型区分,以便 TypeScript 根据字符串文字类型识别特定的集合模式?
  2. 是否有更好的方法来处理这些类型以避免此类类型推断问题?

如果有任何有关如何改进我的类型结构和函数逻辑以确保 TypeScript 正确处理每个集合的特定模式的建议,我将不胜感激。

提前谢谢大家。

node.js typescript types astrojs
1个回答
0
投票

最后我感到绝望,因为找不到令人满意的解决方案,我决定简单地强制强制转换为

CollectionEntry
,如下所示:

import type { CollectionEntry } from 'astro:content';

export async function retrieveCollection (id: CollectionType, preferences = <CollectionSettings>{}) {
  type EntryType = CollectionEntry <typeof id>;

  // The rest of the code remained the same as the code example above.

  if (id === 'blog') {
    entries = entries.filter (({ data }: EntryType) => { }); // Type casting here.
  }
}

虽然这似乎让编译器满意,但我仍然愿意学习更好的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.