You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript/TypeScript中高效实现数据与操作分离?

TypeScript中数据与方法分离的优雅扩展方案

我刚学TypeScript不久,还是个新手。我有函数式编程背景,习惯把对象数据和方法分开写。比如下面这个简单的数据对象,后续会随着代码库扩展需要增强功能:

export interface Data {
  readonly value: number;
}

export function Data(value: number): Data {
  return { value };
}

const data: Data = Data(2);
console.info(data); // 输出 { value : 2 }

Data是我代码的核心模块,包含业务模型核心对象的所有数据。随着应用功能扩展,我想给它添加专用方法,目前想到三种方案:

方案一:使用“伴生对象”模式

export namespace Data {
  export function incr(self: Data): Data {
    return Data(self.value + 1);
  }
}

console.info(data); // 输出 { value : 2 }
Data.incr(data);

这种方案能保持数据是简单对象,也支持扩展,但每次调用方法时语法太啰嗦。

方案二:使用接口模式

export namespace Data {
  export function Ops(self: Data) {
    return {
      self: self,
      incr(): Data {
        return Data(self.value + 1);
      }
    }
  }
}

const data_withops = Data.Ops({ value : 2 });
console.info(data_withops.self); // 输出 { value : 2 }
data_withops.incr() 

语法啰嗦的问题有所缓解,但还是得手动封装/解封装数据。

方案三:将操作注入数据

export interface Data {
  readonly value: number,
  incr(): Data
}

export function Data(value: number): Data {
  return { 
    value,
    incr() {
      return Data(this.value + 1);
    }
  };
}

const data: Data = Data(2);
console.info(data); // 输出 { value : 2, incr : Function }

但这样会让对象体积变大,增加控制台输出、缓存和网络传输的负担。

有没有避开这些问题的实现方式?

我希望满足以下条件:

  • 数据不膨胀:console.info(data); 输出 { value : 2 }
  • 对象使用者不用关心操作的“加载/卸载”
  • 使用者有简洁的语法:可以直接调用data.incr()

我本来以为原型方式可行,但尝试后没成功:

declare global {
  export interface Data {
    incr(this: Data): Data;
  }
}

Data.prototype.incr = function (this: Data): Data {
  return Data(this.value + 1);
};

console.info(data); // 输出 { value : 2 }
data.incr();

内容的提问来源于stack exchange,提问作者Coo LHibou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:25:58