With my first type as
type First = {
a: string,
b: number
}
Open to changes on how the Dictionary
is implemented. A dictionary type could be as follows
type Dictionary = {
string: { "stringValue": string },
number: { "numberValue": number }
}
How do I make it so that I can create some Transform<T>
that I can pass the First
type through so that it will come out as
type Second = {
a: { "stringValue": string },
b: { "numberValue": number }
}
Given I can't read typeof T
I can't figure out how I'd do an indexed access on the Dictionary
. I can do a more manual way of a chain of conditional types, but seems very inelegant
type Dictionary<T> = T extends string ? { "stringValue": string } : { "numberValue": number }
type Second = {[Property in keyof First]: FieldValueOf<First[Property]>}
CodePudding user response:
You will need something like your Dictionary
type, but the fact that they keys are named "string"
and "number"
has nothing to do with the types string
or number
, so it won't help the compiler transform string
types into {stringValue: string}
, without yet another mapping from "string"
to string
. Instead, let's dispense with key names entirely. Like this:
type Mapping =
[string, { "stringValue": string }] |
[number, { "numberValue": number }]
Here Mapping
is a union of 2-tuples where the first element in the tuple is the "from" type, and the second element is the "to" type. You could represent this mapping in other ways (e.g., {from: From, to: To}
instead of [From, To]
) but this is good enough for your purposes.
Then, to map all the properties of a type T
with Mapping
, you can write this:
type UseMapping<T> = { [K in keyof T]: Extract<Mapping, [T[K], any]>[1] };
Here we use the Extract<T, U>
utility type to find the member(s) of Mapping
whose "from" type is compatible with the property type T[K]
, and then from that we extract its "to" type (by indexing into it with the key 1
). Let's see if it works:
type Second = UseMapping<First>;
/* type Second = {
a: {
stringValue: string;
};
b: {
numberValue: number;
};
} */
Looks good!