简体   繁体   中英

Typescript: Use generic type's keys as function's argument object keys

I have a function where the generic type T (which is the fuction's return type) is a dictionary with keys of type string and values of type unknown (because they can be anything). I would like for the single argument that this function takes to be an object whose keys must match those of the generic type T . This is, essentially, a function that maps an object's key/val pairs to a different set of values after some transformation work.

I'd like to use the following (note the index type in the function argument)

export function convert<T extends Record<string, unknown>, S extends keyof any>(items: {
  [key: keyof typeof T]: string
}): T {
  //...do stuff
  return someObj as T;
}

The important thing here is keyof typeof T . This doesn't work as I get an error:

TS2693: 'T' only refers to a type, but is being used as a value here.

I'm not sure how to remedy this, or why T is considered a value here. Does anyone know what I'm doing wrong? The various utility types and index types that I'm using don't seem to resolve my issue. I'd like callers of the function to get warned when they try to pass objects that don't have all keys that match the type once it is defined in the implementation.

Thanks

You have the syntax a bit wrong, a mapped type is what you want not an index signature:

export function convert<T extends Record<string, unknown>>(items: {
  [key in keyof T]: string
}): T {
  //...do stuff
  return items as T;
}

Playground Link

You could also use the Record type instead of a custom mapped type:

export function convert<T extends Record<string, unknown>>(items: Record<keyof T, string>): T {
  //...do stuff
  return items as T;
}

Playground Link

You could also map the other way around if you need to capture more info from the items . Also I find this was more easy to understand, but the displayed type is not expanded by default:

export function convert<T extends Record<string, string>>(items: T): Record<keyof T, unknown> {
  //...do stuff
  return items;
}

Playground Link

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