如何解决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
相关产品推荐
相关产品推荐

