I've looked at other answers that appear to be asking a simplified version of my question, but I can't figure out how to apply them to my specific question. The following code shows what I'm trying to achieve:
type MyStructTrue = {
future_key: string;
future_value: true;
};
type MyStructFalsy = {
future_key: string;
future_value?: false;
};
type MyStruct = MyStructTrue | MyStructFalsy;
const myStructArray = [
{ future_key: 'true1', future_value: true },
{ future_key: 'false1', future_value: false },
{ future_key: 'false2', future_value: undefined },
{ future_key: 'false3' },
] as const satisfies readonly MyStruct[];
type MyStructUnion = (typeof myStructArray)[number];
// I want to build a type of:
// type KeyValues = {
// 'true1': 'yes',
// 'false1': number,
// 'false2': number,
// 'false3': number,
// }
type KeyValues = {
// ^?
[K in MyStructUnion as MyStructUnion['future_key']]: K extends {
future_value: true;
}
? 'yes'
: number;
};
To me it appears that K extends { future_value: true; } ? ...
is applied to all possibilities of MyStructUnion
instead of individual members. As a result, every value of KeyValues
is 'yes' | number
. But I want it to apply that conditional to specific union members to get the type I describe in my code's comment.
I think part of the solution is to use a Distributive Conditional Type, but the type signature of MyStructFalsy
seems to interfere: future_value
may not exist as a property so I am unable to access it in a conditional. I haven't figured out a way to wrap anything in Required<...>
to prevent this.
How do I achieve the KeyValues
type signature in my comment?