Im unsure if that is the correct way to title my question.
What I want to have:
type A = {
foo: number;
}
type B = {
bar: string;
}
ListOfTypes = [A,B]
ListOfPayloads = {
A: A_Payload,
B: B_Payload,
}
type TheoryType = // Insert Magic Here
const a: TheoryType = {
type: "A",
payload: {
foo: 123
}
}
const b: TheoryType = {
type: "B",
payload: {
bar: "123"
}
}
I understand that I could simplify quite easily using the following:
type TheoryType<T extends A | B> = T
Or using a function to explicitly return a specific type.
However, I just wanted to experiment with the limits of typescript and I understand some things may not be possible.
The following is the furthest I got in my experimentation:
const TYPES_NAMES = {
A: "A",
B: "B",
} as const;
type ObjectValues <T> = T[keyof T];
export type TYPES = ObjectValues<typeof TYPES_NAMES>;
export type PAYLOADS = {
A: A_PAYLOAD;
B: B_PAYLOAD;
};
export type TYPE_PAYLOADS<T extends keyof PAYLOADS> = PAYLOADS[T];
export type BODY<Key extends types> = {
type: Key;
payload: TYPE_PAYLOADS<Key>;
}
export type MESSAGE = {
[Key in TYPES]: Body<Key>
}
The above is close but allows any type to match with any payload when using MESSAGE:
// Works
const body: Body<"A"> = {
foo: 123
}
// Doesnt Work
const body: Body<"A"> = {
bar: "123"
}
// Both Work
const body: Message = {
type: "A",
payload: {
foo: 123
}
}
const body: Message = {
type: "A",
payload: {
bar: "123"
}
}
CodePudding user response:
type A = {
foo: number;
}
type B = {
bar: string;
}
type Payload = {
A: A
B: B
}
type TheoryType = { [K in keyof Payload]: { type: K, payload: Payload[K] } }[keyof Payload]
const a: TheoryType = {
type: "A",
payload: {
foo: 123
}
}
const b: TheoryType = {
type: "B",
payload: {
bar: "123"
}
}