如何在不对属性名称进行硬编码的情况下重写代码?

How can I rewrite my code without hardcoding the names of the attributes?

我正在使用 Ramda.js 和 Typescript。为了从对象中获取一些值,我使用 lensPath.

示例:

export interface Store {
    foo: {
       bar: string;
    };
}

const store: Store = {
  foo: {
    bar: 'baz'
  }
};
const fooBarLens = R.lensPath(['foo', 'bar']);

不幸的是,如果我将通过我的 WebStorm 进行一些重构,并将 bar 中的属性 bar 重命名为 baz class Store,那么函数 fooBarLens 将停止工作。

但是如果在重构之前我会重写函数 fooBarLens 就像:

const fooBarLens = (s) => s.foo.bar;

那么重构将正常工作。

如何在不对属性名称进行硬编码的情况下使用 lensPath 和其他 Ramda 函数进行重写并避免重构问题?

我认为对此没有很好的解决方案。它是使用 string-based API 的 trade-offs 之一。我见过的许多重构工具还提供重命名字符串和注释中的 属性,这可能就足够了,尤其是当它引导您完成这些字符串 one-by-one 并为您提供决定时。

但是有一种技术可以使这变得更容易:将数据模型的处理集中在一个模块中。如果您必须在整个 code-base 中更改此类代码,它会变得很丑陋:

const phone = view(lensPath(['contact', 'phones', 'primary'], user);

如果您的用户模块公开 phoneLens 并且您的代码只是

就会容易得多
const phone = view(phoneLens, user)

然后,当您的模型发生变化时,您可以在那个位置切换

const phoneLens = lensPath(['contact', 'phone', 'primary'])

const phoneLens = lensPath(['contacts', 'telephone', 0])

其余代码保持不变。


请记住,在 JavaScript 中,store.foo.bar 格式实际上并不是核心。它只是更基础的 store['foo']['bar'] 版本的语法糖。重构工具可能有一天会赶上这种理解,如果他们还没有这样做的话。