Search code examples
typescriptcastingtype-conversiontypescript-typingstypescript-generics

Can we infer generic typed parameter from function's parameter?


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??

Solution

  • 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.

    Playground