Search code examples
typescriptngrx

Is there a way to use a conditional "type guard" type in a generic argument?


Playground

I have a function, props, which takes in a single generic argument to be used by later consumers.

export function props<P extends object>(): ActionCreatorProps<P> {
  // the value returned isn't important; props is mainly used to consume type information
  return { _as: 'props', _p: undefined! };
}

I want to assert that the type passed in for the generic argument does not violate the following definition:

export type NotAllowedCheck<T extends object> = T extends any[]
  ? ArraysAreNotAllowed
  : T extends { type: any }
  ? TypePropertyIsNotAllowed
  : keyof T extends never
  ? EmptyObjectsAreNotAllowed
  : unknown;

But I can't simply do the following because it violates a circular constraint:

export function props<P extends NotAllowedCheck<P>>(): ActionCreatorProps<P> {
  return { _as: 'props', _p: undefined! };
}

Is there some mechanism that allows these types of assertions in Typescript?


Solution

  • You can break the circular dependency by introducing another generic type (although it does look clumsy)

      function safeProps<P extends (R extends any ?
        P extends object ?
          NotAllowedCheck<P>
          : unknown
        : unknown)
        , R = any>(): ActionCreatorProps<P> 
    

    Playground