Reputation:
I would like to lock the creation of an object by declaring that the keys in it are the concatenation of two types. Since it's blurry, let me picture it with some code :
type Letter = 'A' | 'B' | 'C';
boxes: { [ID in Letter]: string }[] = ...;
Right now, this code allows one to create a set of boxes like this :
boxes = [{ A: 1 }]; // Correct
boxes = [{ D: 1 }]; // Incorrect
What I would like to achieve is do the same thing, but incorporate digits in the keys. Something like this :
type Letter = 'A' | 'B' | 'C';
type Digit = '0' | '1' | '2';
boxes: { [ID in (Letter + '-' + Digit)]: string }[] = ...;
Where a user could then create this
boxes = { 'A-1': 1 };
Is it possible, and if so, how ?
PS : the keys have to be dynamic, i.e. I can't declare a new type made of all possible combinations
Upvotes: 3
Views: 84
Reputation: 249476
No this is not possible, there is no support for manipulation of string literals.
If your set of strings is limited (as in the provided example) then your best bet is to generate all the combinations (should not be that many and you could write a script to generate them)
If you have a lot of possible combinations, then you might do better with just a simple index signature.
Another approach is to redefine your data structure in a way where the second part of the index is actually a nested object, it's more verbose, but typesafe:
type Letter = 'A' | 'B' | 'C';
type Digit = '0' | '1' | '2';
type UnionOfJustOneProperty<T extends string, TAll extends string> = T extends string ? { [P in T]: string } & { [P in Exclude<TAll, T>]?: never }: never;
let boxes: { [P in Letter]: UnionOfJustOneProperty<Digit,Digit> }[] = [
{
A: { "0": "value"},
B: { "1": "value"},
C: { "0": "value", /* "1": "" */} // the commented code causes an error, we can only have one key in the object
}
];
Upvotes: 1
Reputation: 222319
A-1
string requires to evaluate (Letter + '-' + Digit)
at runtime. It's impossible to achieve type safety for such keys in TypeScript.
If type safety is a requirement, keys like A-1
can't be considered an appropriate way.
Upvotes: 2