如何在TypeScript中为数组对象扩展自定义查找方法(不扩展原生对象)
问题描述
我定义了如下TypeScript类型:
export type A = { id: string, name: string } export const data: A[] = [ { id: '1', name: 'Foo' }, { id: '2', name: 'Bar' }, ... ]
每次需要访问数组中的对象时,我都会使用.find方法:
const id = ...; // 获取ID data.find((entry) => entry.id === id)?.name ... data.find((entry) => entry.name === name)?.name
由于相同的查找操作出现在代码的多个位置,我希望为data对象扩展自定义方法,例如:
findById(id: string)findByName(name: string)- ...
之后可以通过如下方式调用这些方法获取数组条目:
... data.findById('1').name; ... data.findByName('Foo').id;
请问是否可以在TypeScript中实现该需求,且无需扩展原生Object?
解决方案
当然可以实现,以下是几种无需扩展原生对象的可行方案:
方案1:自定义类封装数组
定义继承自Array的类,添加自定义查找方法,再用该类初始化数据:
export type A = { id: string, name: string } class DataArray extends Array<A> { findById(id: string): A | undefined { return this.find(entry => entry.id === id); } findByName(name: string): A | undefined { return this.find(entry => entry.name === name); } } // 初始化数据 export const data = new DataArray( { id: '1', name: 'Foo' }, { id: '2', name: 'Bar' } ); // 使用示例 data.findById('1')?.name; // "Foo" data.findByName('Bar')?.id; // "2"
这种方式保留了数组所有原生方法,同时新增自定义逻辑,TypeScript类型推导完全正常。
方案2:为数组实例添加方法并补全类型
无需创建类,直接给data添加方法,通过类型声明让TypeScript识别自定义方法:
export type A = { id: string, name: string } // 定义包含自定义方法的复合类型 type DataWithMethods = A[] & { findById: (id: string) => A | undefined; findByName: (name: string) => A | undefined; }; // 初始化原始数组 const rawData: A[] = [ { id: '1', name: 'Foo' }, { id: '2', name: 'Bar' } ]; // 添加自定义方法并断言类型 export const data = rawData as DataWithMethods; data.findById = function(id) { return this.find(entry => entry.id === id); }; data.findByName = function(name) { return this.find(entry => entry.name === name); }; // 使用示例 data.findById('1')?.name; data.findByName('Foo')?.id;
这种方式更轻量化,直接给目标数组实例扩展方法,无需额外类结构。
方案3:封装独立工具函数
如果不想修改原数组对象,可把查找逻辑封装成独立工具函数:
export type A = { id: string, name: string } export const data: A[] = [ { id: '1', name: 'Foo' }, { id: '2', name: 'Bar' } ]; // 工具函数 export const findById = (id: string) => data.find(entry => entry.id === id); export const findByName = (name: string) => data.find(entry => entry.name === name); // 使用示例 findById('1')?.name; findByName('Bar')?.id;
这种方式最简洁,无需修改数组本身,适合不需要链式调用的场景。
内容的提问来源于stack exchange,提问作者lucio
相关产品推荐
相关产品推荐

