I have an interface like this:
interface ISession {
    emailAddress: string;
    me: IUser | null;
    groups: IGroup[] | null;
}
I want to create a an object with this pseudo-code:
type SetAction = {
    type: typeof SET,
    key: K in keyof ISession,
    value: V in valueof ISession
};
The problem with this pseudocode is it does not ensure that the value type matches the value of ISession[k].
Is this possible in TS?
A similar problem I had to this, this is not apart of the question, but to help others maybe think, because i feel the solution would be the same. I need to write a function function set(key, value). Where the key and value are of the approprate matching pair.
You can create such a type but what you want to do is create a union of all possible key/value combinations. So the type we want to create is: 
type SetAction  = 
    { type: typeof SET, key: 'emailAddress', value: string; } |
    { type: typeof SET, key: 'me', value:  IUser | null; } |
    { type: typeof SET, key: 'groups', value: IGroup[] | null; }
We can do this by using a distributive conditional type
type SetAction = keyof ISession extends infer K ? // introduce type parameter 
    K extends keyof ISession ? // distribute over the type parameter 
        { type: typeof SET, key: K, value: ISession[K]; } // The type that we construct for each K
    : never: never
Or a perfhaps simpler to understand version using mapped types (the result is the same):
type SetAction = {
    [K in keyof ISession]-?: { type: typeof SET, key: K, value: ISession[K]; } 
}[keyof ISession]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With