Reputation: 53
I have started learning typescript. I am sure there might be a similar ticket as this but wanted a quick view into this.
i have keys
type keys = 'a' | 'e' | 'i' | 'o' | 'u';
I want these to restrict the possible a keys in an object
{
numbers : number;
symbols : string;
[key : keys] : string | number | boolean;
}
However i get this error An index signature parameter type cannot be a union type. Consider using a mapped object type instead.
so i tried
{
numbers : number;
symbols : string;
[key in keys] : string | number | boolean;
}
but I got another error
from TSLint.
I hope if somebody can help me out with these with examples why and how do they vary? and solution Please.
The result I want is
key with only values of a, e, i, o, u and these Keys can have any of the string, number, boolean types of values.
Upvotes: 3
Views: 3300
Reputation: 28590
type keys = 'a' | 'e' | 'i' | 'o' | 'u'
type Dynamic = {
[index in keys]: string | number | boolean
}&{
numbers : number;
symbols : string;
}
Upvotes: 0
Reputation: 328618
Mapped types are similar to index signatures, but they are not the same. As you discovered, the keys of index signatures can only be exactly string
or number
. Mapped types allow you to specify a narrower set of keys, but you can't add other properties to a mapped type.
What you can do is use an intersection:
type X = {numbers: number; symbols: string} & {[K in keys]: string | number | boolean}
// type X = {
// numbers: number;
// symbols: string;
// } & {
// a: string | number | boolean;
// e: string | number | boolean;
// i: string | number | boolean;
// o: string | number | boolean;
// u: string | number | boolean;
// }
This is essentially the same as what you want, since the intersection A & B
means that you must conform to both A
and B
.
Another way to represent this type is to use a mapped conditional type for the whole thing instead of an intersection. This will be more complicated-looking for you, but evaluates to something nicer for people to use:
type Y = { [K in "numbers" | "symbols" | keys]:
K extends "numbers" ? number :
K extends "symbols" ? string :
string | number | boolean };
// type Y = {
// a: string | number | boolean;
// e: string | number | boolean;
// i: string | number | boolean;
// o: string | number | boolean;
// u: string | number | boolean;
// numbers: number;
// symbols: string;
Either way should work. Hope that helps; good luck!
Upvotes: 1