So code looks like something like this:
enum Status {
Open = "open",
Closed = "closed"
}
interface DefaultRequest {
status: Status
}
interface OpenRequest extends DefaultRequest {
status: Status.Open;
data?: Record<string, Status.Open>
}
interface CloseRequest extends DefaultRequest {
status: Status.Close;
data?: Record<string, Status.Close>
}
interface MapRequest {
[Status.Open]: OpenRequest;
[Status.Close]: CloseRequest;
}
type Request = OpenRequest | CloseRequest;
function isValidRequestType<T extends Status> (data: Request): T is MapRequest[T] {
return true;
}
isValidRequest<Status.Open>({ status: Status.Open }) //passed argument is typecasted to OpenRequest
isValidRequest({ status: Status.Open }) // passed argument is typecasted to Request
Is it possible that if I don't pass the generic parameter at function call and isValidRequest can still infer the status from the passed argument's attribute (aka status)?
Something like
function isValidRequestType<T extends Status> (data: Request & {type: T}): T is MapRequest[T] {
return true;
}
isValidRequest({ status: Status.Open }) // passed argument is OpenRequest??
You were close, but I think you want something like:
function isValidRequestType<T extends Status>(
data: Request & { status: T }
): data is Request & { status: T } {
return true;
}
When you do data is Request & { status: T }
you are saying the argument named data
is the union Request
with only the members that match { status: T }
. This narrows that union to only the options that have that status.