You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决readonly数组传入非readonly函数的TypeScript类型错误?

解决DataLoader与readonly数组的类型冲突问题

这里的核心矛盾是:DataLoader要求批量函数接收readonly string[]类型参数,但User.findBy的参数只接受可变的string[],两边类型不兼容。给你几个靠谱的解决办法:

方案1:类型断言(简单直接)

既然你确定User.findBy不会修改传入的数组,直接用类型断言把readonly string[]转成string[]就行:

type BatchUser = (ids: readonly string[]) => Promise<User[]>;

const batchUsers: BatchUser = async (ids) => {
  // 用as string[]做类型断言
  const users = await User.findBy({ id: In(ids as string[]) });

  const userMap: { [key: string]: User } = {};
  users.forEach((u) => {
    userMap[u.id] = u;
  });
  return ids.map((id) => userMap[id]);
};

export const userLoader = () => new DataLoader<string, User>(batchUsers);

方案2:创建可变数组副本(更安全)

如果不想用断言,或者担心后续代码误修改数组,可以把readonly数组转成新的可变数组:

type BatchUser = (ids: readonly string[]) => Promise<User[]>;

const batchUsers: BatchUser = async (ids) => {
  // 展开创建新的可变数组
  const mutableIds = [...ids];
  const users = await User.findBy({ id: In(mutableIds) });

  const userMap: { [key: string]: User } = {};
  users.forEach((u) => {
    userMap[u.id] = u;
  });
  return ids.map((id) => userMap[id]);
};

export const userLoader = () => new DataLoader<string, User>(batchUsers);

方案3:修改User.findBy的类型定义(根源解决)

如果有权限修改User.findBy的类型,直接把它的参数改成readonly string[]是最合理的——毕竟查询函数不需要修改传入的ID数组,用readonly更符合类型安全原则:

// 假设原findBy类型是这样,把string[]改成readonly string[]
type FindByOptions = {
  id: In<readonly string[]>;
};

// 或者直接修改findBy的参数类型
class User {
  static findBy(options: { id: In<readonly string[]> }): Promise<User[]> {
    // 实现代码
  }
}

这样修改后,原代码不需要任何改动就能正常运行,类型检查也能通过。

内容的提问来源于stack exchange,提问作者sev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 17:05:32