react-admin拆分资源provider实现自定义dataProvider时的TypeScript报错问题
错误原因
你当前的ResourceProvider类型定义把泛型RecordType声明在了getList方法层级,这意味着该方法需要兼容调用方传入的任意符合Record约束的RecordType类型,但你在transactionProvider的实现里固定返回了Transaction[]类型,TypeScript无法保证Transaction可以匹配调用方传入的任意RecordType子类型,因此抛出类型错误。
解决方案
第一步:调整ResourceProvider的泛型位置
把泛型从方法层级提到类型层级,让每个资源Provider可以绑定自己独有的记录类型:
// resourceProvider.ts export type ResouceProvider<T extends Record = Record> = { getList: (params: GetListParams) => Promise<GetListResult<T>>; // 其他方法(getOne、create等)同理,把原来的RecordType替换为T即可 };
第二步:实现资源Provider时指定对应的记录类型
实现transactionProvider时给ResouceProvider传入Transaction作为泛型参数:
// transactionProvider.ts import { Transaction } from 'types'; import { ResouceProvider } from './resourceProvider'; // 这里指定泛型为Transaction const transactionProvider: ResouceProvider<Transaction> = { getList: async (params: GetListParams) => { const { start, end } = params.filter; const res = await fetchTransactions(start, end); const result = []; for (let item of res.data.data) { const transaction: Transaction = item.data; transaction.id = item.id; result.push(transaction); } return { data: result, total: result.length }; }, // 其他方法实现不变 }; export default transactionProvider;
第三步:根dataProvider添加类型断言
因为不同资源的Provider对应不同的泛型类型,TypeScript无法自动推导统一的返回类型,你可以在调用Provider方法时添加类型断言,运行时你保证资源名和Provider的对应关系即可:
// dataProvider.ts import { ResouceProvider } from './resourceProvider'; import transactionProvider from './transactionProvider'; const providers: { [key: string]: ResouceProvider } = { transactions: transactionProvider, }; const dataProvider: DataProvider = { getList: <RecordType extends Record = Record>(resource: string, params: GetListParams) => { return providers[resource].getList(params) as Promise<GetListResult<RecordType>>; }, // 其他方法同理添加断言 }; export default dataProvider;
如果你的项目对类型严谨度要求高,也可以额外声明资源和类型的映射表,进一步收窄类型避免写错资源名,普通项目用上面的断言方案已经足够。
内容的提问来源于stack exchange,提问作者e-j5
相关产品推荐
相关产品推荐

