如何在Typescript中键入用于重命名对象键的函数

时间:2019-06-13 16:03:26

标签: typescript object key rename

我有一个函数,它带有一个字符串转换函数和一个对象,并将转换应用于所有键,并返回结果对象。

特别是我在使用Ramda

这是我的功能(为清晰起见,未键入)。

const renameBy = R.curry(
  (fn, obj) => R.pipe(
      R.toPairs,
      R.map([k, v] => [fn(k), v]),
      R.fromPairs
    )(obj)
);

我很清楚currying可能引起的问题,所以我真的只在寻找解决核心函数(以及可选的第二个一元函数namedBy(fn))的解决方案,并解决比当前更好的返回类型R.Dictionary,它基本上从不匹配任何东西。

我一直在寻找here, dealing with renaming specific keys of an objecthere, dealing with recursive, deep nested-object renaming,但似乎都不是我要找的东西。

用法示例

const input = {
     foo_bar: "foobar",
     bar: "bar",
     bar_foo: "barfoo"
}

const camelize = (paramName) =>
  paramName.replace(
    /_(.?)/g,
    $1 => $1.substr(1).toUpperCase()
  );

renameBy(camelize, input)

const expectedOutput = {
     fooBar: "foobar",
     bar: "bar",
     barFoo: "barfoo"
}

我可能会使用类似的东西

function renameBy<
     F extends (str: string) => string,
     N extends string[],
     M extends Record<string, any>
   >(fn: F, obj: M): { [P in N]: M[keyof M] }
      {...}

但是我不能完全正常工作。

1 个答案:

答案 0 :(得分:0)

距离讨论这个问题已经有一段时间了。最近,我面临着类似的任务。无论如何,这是 TS 4.1+ 的可能解决方案

// helper types
type BaseT = Record<string, unknown> // object constraint
type BaseM = Record<string, string> // mapping constraint
type KVs<T extends BaseM> = keyof T | T[keyof T] // keys and values

type Remap<T extends BaseT, M extends BaseM> =
  & {[K in keyof M & keyof T as M[K]]: T[K]} // new keys
  & {[K in keyof T as Exclude<K, KVs<M>>]: T[K]} // unchanged keys

type Result = Remap<{a: 1; b: '2'}, {a: 'c'}>
// type Result = {b: '2'} & {c: 1}