有没有办法在通用参数中使用条件 "type guard" 类型?

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

Playground

我有一个函数,props,它接受一个通用参数供以后的消费者使用。

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! };
}

我想断言为泛型参数传入的类型不违反以下定义:

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

但我不能简单地执行以下操作,因为它违反了循环约束:

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

是否有某种机制允许在 Typescript 中使用这些类型的断言?

您如何看待在 return 类型中使用检查助手?

// Declaring some constraint error messages
export const arraysAreNotAllowedMsg =
  'arrays are not allowed in action creators';
type ArraysAreNotAllowed = typeof arraysAreNotAllowedMsg;

export const typePropertyIsNotAllowedMsg =
  'type property is not allowed in action creators';
type TypePropertyIsNotAllowed = typeof typePropertyIsNotAllowedMsg;

export const emptyObjectsAreNotAllowedMsg =
  'empty objects are not allowed in action creators';
type EmptyObjectsAreNotAllowed = typeof emptyObjectsAreNotAllowedMsg;

// The constraint on props
export type NotAllowedCheck<T> = T extends object ? T extends any[]
  ? ArraysAreNotAllowed
  : T extends { type: any }
  ? TypePropertyIsNotAllowed
  : keyof T extends never
  ? EmptyObjectsAreNotAllowed
  : unknown : never

export interface ActionCreatorProps<T> {
  _as: 'props';
  _p: T;
}



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

// ActionCreatorProps<"type property is not allowed in action creators">
const someProps = safeProps<{ type: string }>();

你可以通过引入另一个泛型来打破循环依赖(虽然它看起来很笨拙)

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

Playground