In my Project, I am using a mapped type (with string
s as keys):
export type ConfigurableFieldsType<T extends string[]> = {
[field in keyof T]: string
}
In the following method, I am using the type (this.configurableFields
is a ConfigurableFieldsType
object):
private getConfigurableAttribute(attribute: C[number]): string {
return this.configurableFields[attribute]
}
However, I am getting the error:
Type 'C[number]' cannot be used to index type 'ConfigurableFieldsType<C>'.
You can find the complete example (with reproducible error) in this TS Playground or in the following:
export type ProductType<T extends string[]> = {
// more variables
configurableFields: ConfigurableFieldsType<T>
}
export type ConfigurableFieldsType<T extends string[]> = {
[field in keyof T]: string
}
export class Product<C extends string[]> implements ProductType<C> {
constructor(
// more public parameters
public configurableFields: ConfigurableFieldsType<C>,
) {}
private getConfigurableAttribute(attribute: C[number]): string {
return this.configurableFields[attribute]
}
}
CodePudding user response:
You intend ConfigurableFieldsType<["a", "b", c"]>
to evaluate to something like {a: string, b: string, c: string}
, but your current definition would result in [string, string, string]
. That's because {[K in keyof T]: string}
results in a mapped array type; T
is an arraylike type, and keyof T
is thus the array keys, like "push"
or "length"
.
Instead, you want the keys of your type to be elements of T
. That is, the types you get when you index into T
with a numeric index... so instead of keyof T
, you want T[number]
:
export type ConfigurableFieldsType<T extends string[]> = {
[K in T[number]]: string
}
type Example = ConfigurableFieldsType<["a", "b", "c"]>
/* type Example = {
a: string;
b: string;
c: string;
} */
And now things work as you intend:
private getConfigurableAttribute(attribute: C[number]): string {
return this.configurableFields[attribute] // okay
}