如何异步加载Ag Grid集合筛选器的复杂类型值?
我在尝试为Ag Grid集合筛选器(Set Filter)的filterParams.values设置异步加载函数时,碰到了复杂对象数组被转换为"[Object Object]"的问题。简单字符串数组加载正常,但复杂类型(比如下面的IAmNotJustANumber)无法正确渲染:
interface IAmNotJustANumber { id: number; name: string; }
问题核心在于SetFilterValuesFuncParams的success方法TypeScript类型定义仅接受string[],即使强制转为any,内部仍会自动执行字符串转换,导致复杂对象失效。虽然官方文档说明集合筛选器支持复杂类型,只需配合keyCreator和valueFormatter,但数据无法正确传入的话这些配置也起不了作用。
我曾尝试用JSON.stringify将对象转为字符串,再在keyCreator和valueFormatter中反序列化,但这种方式不够规范:
filterParams: { values: (params) => { loadData().then(response => params.success(response.data.map(d => JSON.stringify(d)) ) }, keyCreator: (params) => { const v : IAmNotJustANumber = JSON.parse(params.value); return v.id; }, valueFormatter: (params) => { const v : IAmNotJustANumber = JSON.parse(params.value); return `${v.id} [${v.name}]`; } }
正确解决方案:绕过类型限制直接传入对象数组
实际上这不是Ag Grid的实现疏漏,而是TypeScript类型定义的局限性。Ag Grid内部支持直接传入复杂对象数组,只需通过类型断言绕过TS检查,同时配合keyCreator和valueFormatter即可:
filterParams: { values: (params: SetFilterValuesFuncParams) => { loadData().then(response => { // 用类型断言让TS接受对象数组 (params.success as (values: IAmNotJustANumber[]) => void)(response.data); }); }, keyCreator: (params) => { // params.value现在是IAmNotJustANumber类型 const v = params.value as IAmNotJustANumber; return v.id.toString(); // 必须返回字符串作为唯一标识 }, valueFormatter: (params) => { const v = params.value as IAmNotJustANumber; return `${v.id} [${v.name}]`; } }
更优雅的类型扩展方案
如果不想每次都写类型断言,可以扩展Ag Grid的TypeScript类型定义,让success支持泛型:
declare module '@ag-grid-community/core' { interface SetFilterValuesFuncParams { success: <T>(values: T[]) => void; } }
之后就能直接传入对象数组,无需额外断言:
values: (params: SetFilterValuesFuncParams) => { loadData().then(response => params.success<IAmNotJustANumber>(response.data)); }
总结
不需要用JSON序列化这种hack方式,通过类型断言或扩展类型定义,配合keyCreator(提供唯一标识)和valueFormatter(控制显示内容),就能优雅实现复杂对象数组的异步加载。
内容的提问来源于stack exchange,提问作者Ryan Pierce Williams

