如何为TypeScript接口定义的Product类型添加扩展方法?
给Product类型添加扩展方法的两种实现方案
由于TypeScript接口无法直接定义方法,结合你项目中使用的ts.data.json解码库,这里提供两种实用方案:
方案一:将接口改为类,让解码器返回类实例
这种方式更符合面向对象设计,适合后续扩展更多方法:
- 把原Product接口替换为类,并实现所需方法
export class Product { readonly id: string; readonly attributes: ReadonlyArray<string>; // 补充其他属性定义 constructor(id: string, attributes: ReadonlyArray<string>, /* 其他属性参数 */) { this.id = id; this.attributes = attributes; // 初始化其他属性 } hasAbc(): boolean { // 注意:JS/TS数组用includes而非contains return this.attributes.includes("abc"); } hasDef(): boolean { return this.attributes.includes("def"); } }
- 修改解码器,通过
map方法将解码后的普通对象转为Product类实例
export const productDecoder = JsonDecoder.object<Product>( { id: JsonDecoder.string, attributes: JsonDecoder.array(JsonDecoder.string), // 其他属性对应的解码器 }, "Product" ).map( (rawObj) => new Product(rawObj.id, rawObj.attributes, /* 传入其他属性 */), "Product instance" );
之后调用getProduct()拿到的就是Product类实例,直接调用product.hasAbc()即可。
方案二:使用包装函数扩展对象(不改动原有接口)
如果不想修改原有接口结构,可在解码后用包装函数给对象添加方法:
- 扩展Product类型,定义方法的类型声明
export interface ProductWithMethods extends Product { hasAbc(): boolean; hasDef(): boolean; }
- 编写包装函数,给原Product对象注入方法
export function wrapProduct(product: Product): ProductWithMethods { return { ...product, hasAbc(): boolean { return this.attributes.includes("abc"); }, hasDef(): boolean { return this.attributes.includes("def"); } }; }
- 修改
getProduct函数,在解码完成后调用包装函数
export async function getProduct(): Promise<ProductWithMethods> { return new Promise((resolve, reject) => { customAxios.get("/api/products/123") .then(response => decodeResponse<Product>(productDecoder, response.data) .then(wrapProduct) .then(resolve) .catch(reject) ) .catch(error => reject(pathOr("Error...", errorMsgPath, error))); }); }
这样获取到的Product对象同样支持直接调用hasAbc()和hasDef()方法。
内容的提问来源于stack exchange,提问作者Blankman
相关产品推荐
相关产品推荐

