Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Keys and value type checking in typescript

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.
like image 714
Gagan Deep Avatar asked Feb 25 '26 14:02

Gagan Deep


1 Answers

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!

like image 199
jcalz Avatar answered Feb 28 '26 05:02

jcalz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!