打字稿:从具有泛型的对象获取键映射

时间:2021-01-26 04:55:24

标签: typescript typescript-generics

我想从任何对象获取键映射,

我已经实现了这个功能,

但我不能让打字稿快乐,

不使用acc: any我该怎么办

const origin = {
  a: 1,
  b: 'string',
  c: () => {}
};

function getObjKeyMap<T>(obj: T) {
  return Object.keys(obj).reduce((acc, k) => {
 /* Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
  No index signature with a parameter of type 'string' was found on type '{}'.ts(7053) */
    acc[k] = k;
    return acc;
  }, {});
}

const keyMap = getObjKeyMap(origin);

1 个答案:

答案 0 :(得分:2)

您需要告诉 reduce 用于累加器的对象类型。

const originObj = {
  a: 1,
  b: 'string',
  c: () => {}
};

function getObjKeyMap<T>(obj: T) {
  return Object.keys(obj).reduce((acc, k) => {
    acc[k] = k;
    return acc;
  }, {} as Record<string, string>);
}

// or


function getObjKeyMap1<T>(obj: T) {
  return Object.keys(obj).reduce((acc: Record<string, string>, k: string) => {
    acc[k] = k;
    return acc;
  }, {});
}

const keyMap = getObjKeyMap(originObj);

TS Playground

但是,我敢打赌这不是最好的解决方案。我敢打赌有一种方法可以编写这样的函数声明:

function getObjKeyMap<T, K extends keyof T>(obj: T): Record<K, K>

Typescript 会自动告诉您 getObjectMap({a: 1, b: 'string', c: () => {}} 返回 {a: "a", b: "b", c: "c"}

我认为这要好得多:

const originObj = {
  a: 1,
  b: 'string',
  c: () => {}
};

type KeyMap<T> = {
  [key in keyof T]: key
};

function getObjKeyMap<T>(obj: T): KeyMap<T> {
  return Object.keys(obj).reduce((acc, k) => ({...acc, k: k}), {} as KeyMap<T>);
}


const keyMap = getObjKeyMap<typeof originObj>(originObj);

TS Playground