To begin with, I have a specific desired outcome:
type Wrapper<ID extends string> = { id: ID };
type WrapperWithPayload<ID extends string, Payload> = { id: ID, payload: Payload };
enum IDs {
FOO = "ID Foo",
BAR = "ID Bar",
BAZ = "ID Baz"
}
interface AssociatedTypes {
[IDs.FOO]: number;
[IDs.BAR]: number[];
}
type Result = MagicMapper<IDs, AssociatedTypes>
/*
* Result should have this type:
* {
* [IDs.FOO]: WrapperWithPayload<IDs.FOO, number>;
* [IDs.BAR]: WrapperWithPayload<IDs.BAR, number[]>;
* [IDs.BAZ]: Wrapper<IDs.BAZ>;
}
*/
In simple terms, I wish to provide strings and a mapping where some strings are associated with another type. Then, I aim to generate a new type using the supplied strings as keys. If there is a mapping for a specific string/key, I want to use one type, if not, then another type.
Currently, my approach is like this:
type MagicMapper<T extends string, Mapping extends { [key in T]?: any }> = {
[key in T]: Mapping[key] extends never ? Wrapper<key> : WrapperWithPayload<key, Mapping[key]>;
};
And it almost achieves the intended result:
type Result = {
"ID Foo": WrapperWithPayload<IDs.FOO, number>;
"ID Bar": WrapperWithPayload<IDs.BAR, number[]>;
"ID Baz": Wrapper<IDs.BAZ> | WrapperWithPayload<IDs.BAZ, any>;
}
The error lies in the union on the key for Baz. I suspect the issue stems from the extends never
condition, but changing it to, for example, undefined only exacerbates the situation:
type MagicMapper<T extends string, Mapping extends { [key in T]?: any }> = {
[key in T]: Mapping[key] extends undefined ? Wrapper<key> : WrapperWithPayload<key, Mapping[key]>;
};
type Result = {
"ID Foo": Wrapper<IDs.FOO>;
"ID Bar": Wrapper<IDs.BAR>;
"ID Baz": Wrapper<IDs.BAZ>;
}
Is there a way to align things to meet my requirements?