Suppose I have two types:
type Credentials = {
Username: string;
Password: string;
};
type XmlCredentials = { [k in keyof Credentials]: { _text: string } };
and I want to convert from Credentials
to XmlCredentials
, wrapping string
values of input properties with { _text: _ }
object.
I can easily do this manually:
const convertNonGenericManual = (input: Credentials): XmlCredentials => ({
Username: {
_text: input.Username,
},
Password: {
_text: input.Password,
},
});
but this gets cumbersome and repetitive when input types has many properties.
I tried writing the function without repetition:
const convertNonGenericManual = (input: Credentials): XmlCredentials => {
// TODO this does not type check
return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, { _text: value }]));
};
And even generically:
const convertGeneric = <T extends readonly string[]>(input: { [k in T[number]]: string }): { [k in T[number]]: { _text: string }; } => {
// TODO this does not type check
return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, { _text: value }]));
};
But I was unable to get it to type-check in either case.
Is it possible to achieve this without writing boilerplate code?
Edit:
I think that the problem reduces to being able to iterate over a tuple and having the narrow type in each iteration, which I imagine might not be possible:
const values = ["k1", "k2"] as const;
for (const v of values) {
// we'd need v
to have type "v1"
during first iteration and "v2"
during second iteration - probably impossible
}