How do I add an index signature for a mapped type?

笑着哭i 提交于 2020-12-01 02:33:22

问题


Suppose I have interface

interface X {
   a: string;
   b: number;
   c: boolean;
}

and a function

function values(x: X) {
   return Object.keys(x).map(s => x[s])
}

When I enable typescript's strict flag I get the error "Element implicitly has an 'any' type because type 'X' has no index signature". So to make it explicit, I can just add an index signature to the definition of X

[key: string]: any;

Easy peasy.


However if I X is now a mapped type instead:

type X<T> = {
  [P in keyof T]: string;
}

and I have the function

function values<T>(x: X<T>) {
  return Object.keys(x).map(s => x[s])
}

where am I supposed to add the index signature? Is there any way to make this explicit without resorting to doing something gross like Object.keys(x).map(s => (x as any)[s])


回答1:


You can:

interface X {
    a: string;
    b: number;
    c: boolean;
    [key: string]: X[keyof X];
}

The result of X[keyof X] will now be (string | number | boolean), which works even better than any because the return of your function will be (string | number | boolean)[].

Example

Another way that should work with both examples is:

function values(x: X) {
    const keys = Object.keys(x) as (keyof X)[];
    return keys.map(s => x[s]);
}

Not pretty, but at least more typed than (x as any).

Of course it can be made generic too:

function values<T>(x: T) {
    const keys = Object.keys(x) as (keyof T)[];
    return keys.map(s => x[s]);
}


来源:https://stackoverflow.com/questions/47464764/how-do-i-add-an-index-signature-for-a-mapped-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!