Conditional Types
Response Payload Type
Conditional types can extract the payload type from a tagged response shape.
payload extraction
Combining `extends` with `infer` can extract a nested type while a runtime branch handles success and failure.
Response Payload Type
payload.ts
Replay: real traced execution (multi-file project)
type Success<T> = { ok: true; value: T };
type Failure = { ok: false; error: string };
type Response<T> = Success<T> | Failure;
type PayloadOf<T> = T extends Success<infer U> ? U : string;
function describeResponse<T>(response: Response<T>): string {
if (response.ok) {
const payload: PayloadOf<Success<T>> = response.value;
return `value:${payload}`;
}
const payload: PayloadOf<Failure> = response.error;
return `error:${payload}`;
}
const okResponse: boolean = true;
const response: Response<number> = okResponse ? { ok: true, value: 7 } : { ok: false, error: "missing" };
console.log(describeResponse(response));
type Success<T> = { ok: true; value: T };
type Failure = { ok: false; error: string };
type Response<T> = Success<T> | Failure;
type PayloadOf<T> = T extends Success<infer U> ? U : string;
function describeResponse<T>(response: Response<T>): string {
if (response.ok) {
const payload: PayloadOf<Success<T>> = response.value;
return `value:${payload}`;
}
const payload: PayloadOf<Failure> = response.error;
return `error:${payload}`;
}
const okResponse: boolean = false;
const response: Response<number> = okResponse ? { ok: true, value: 7 } : { ok: false, error: "missing" };
console.log(describeResponse(response));
okResponse ← true, response ← [object Object]
13 return `error:${payload}`;14}1516const okResponse→ true: boolean = true; //@okResponse=false17const response→ [object Object]: Response<number> = okResponsetrue ? { ok: true, value: 7 } : { ok: false, error: "missing" };1819console.log(describeResponse(response[object Object]));function describeResponse<T>(response: Response<T>): string
5type PayloadOf<T> = T extends Success<infer U> ? U : string;67function describeResponse<T>(response[object Object]: Response<T>): string {8 if (response.ok) {payload ← 7, response.value ← 7
7function describeResponse<T>(response: Response<T>): string {8 if (response.oktrue) {9 const payload→ 7: PayloadOf<Success<T>> = response.value→ 7;10 return `value:${payload7}`;11 }values this step[object Object]responseconsole.log(describeResponse(response));
16const okResponse: boolean = true; //@okResponse=false17const response: Response<number> = okResponse ? { ok: true, value: 7 } : { ok: false, error: "missing" };1819console.log(describeResponse(response[object Object]));outputvalue:7
okResponse ← false, response ← [object Object]
13 return `error:${payload}`;14}1516const okResponse→ false: boolean = false;17const response→ [object Object]: Response<number> = okResponsefalse ? { ok: true, value: 7 } : { ok: false, error: "missing" };1819console.log(describeResponse(response[object Object]));payload ← missing, response.error ← missing
5type PayloadOf<T> = T extends Success<infer U> ? U : string;67function describeResponse<T>(response[object Object]: Response<T>): string {8 if (response.ok) {9 const payload: PayloadOf<Success<T>> = response.value;10 return `value:${payload}`;11 }12 const payload→ missing: PayloadOf<Failure> = response.error→ missing;13 return `error:${payloadmissing}`;14}console.log(describeResponse(response));
16const okResponse: boolean = false;17const response: Response<number> = okResponse ? { ok: true, value: 7 } : { ok: false, error: "missing" };1819console.log(describeResponse(response[object Object]));outputerror:missing