无法访问联合类型中非共有属性,TypeScript分页函数报错
解决TypeScript联合类型数组方法报错问题
你的问题核心是TypeScript无法自动窄化联合类型Results的类型——因为它既可能是object[],也可能是单个User或Query对象,直接调用length和slice会触发类型检查错误,毕竟这两个方法只有数组才具备。
下面是两种可行的解决思路:
1. 归一化处理输入,统一转为数组
在分页逻辑开始前,先把单个对象包装成单元素数组,确保后续操作都基于数组类型:
type Results = object[] | User | Query; class Pagination implements IPagination { totalPages: any[]; readonly itemsPerPage = 5; public async Paginate(items: Results, page: number): Promise<Page> { // 将非数组输入转为单元素数组,统一处理逻辑 const normalizedItems = Array.isArray(items) ? items : [items]; const pages = Math.ceil(normalizedItems.length / this.itemsPerPage); const paginatedItems = Array.from({ length: pages }, (_, index) => { const start = index * this.itemsPerPage; return normalizedItems.slice(start, start + this.itemsPerPage); }); this.totalPages = [...paginatedItems]; // 处理page超出范围的情况,避免返回undefined return { totalPages: this.totalPages, currentPageRows: this.totalPages[page] || [], itemsPerPage: this.itemsPerPage }; } }
这种方式的好处是保持了原方法的参数灵活性,同时通过Array.isArray()做类型守卫,让TypeScript明确知道normalizedItems是数组类型,消除报错。
2. 使用方法重载明确参数类型
如果希望更清晰地定义方法的输入类型,可以通过方法重载区分数组和单个对象的情况:
type Results = object[] | User | Query; class Pagination implements IPagination { totalPages: any[]; readonly itemsPerPage = 5; // 重载签名:分别定义数组和单个对象的输入 public async Paginate(items: object[], page: number): Promise<Page>; public async Paginate(items: User | Query, page: number): Promise<Page>; // 实现签名:处理联合类型 public async Paginate(items: Results, page: number): Promise<Page> { const normalizedItems = Array.isArray(items) ? items : [items]; // 后续逻辑和第一种方案一致 const pages = Math.ceil(normalizedItems.length / this.itemsPerPage); const paginatedItems = Array.from({ length: pages }, (_, index) => { const start = index * this.itemsPerPage; return normalizedItems.slice(start, start + this.itemsPerPage); }); this.totalPages = [...paginatedItems]; return { totalPages: this.totalPages, currentPageRows: this.totalPages[page] || [], itemsPerPage: this.itemsPerPage }; } }
方法重载能让调用方更清楚地知道方法支持的输入类型,同时内部依然可以复用归一化的逻辑。
另外建议:如果你的分页逻辑本质上只应该处理列表数据,也可以考虑直接修改Results类型,去掉User | Query,让方法只接收数组参数——这样从根源上避免类型歧义,代码会更简洁。
内容的提问来源于stack exchange,提问作者JustBarnt
相关产品推荐
相关产品推荐

