简体   繁体   中英

typescript: get an key map from object with generic

I want to get the key map from any object,

I've implemented the function,

but I can't make typescript happy,

what should I do without using 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);

You need to tell the type of object that reduce uses for accumulator.

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

However, I bet this is not the best solution. I bet there is a way to write a function declaration like this:

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

Where Typescript automatically tells you that getObjectMap({a: 1, b: 'string', c: () => {}} returns {a: "a", b: "b", c: "c"} .

I think this is much better:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM