打字稿如何有条件地包含类型?

时间:2021-04-14 09:04:48

标签: javascript typescript

我有一个案例,我需要在 Typescript 中有条件地包含类型。我不是 100% 肯定它甚至可能使用 Typescript。

我在下面的示例中简化了代码。

type FlexBoxType = {
  inline?: boolean;
  justifyContent?: string;
  alignItems?: string;
    
  /* and so on */
}

type FlexItemType = {
  box?: boolean;
  flex?: string|number;
  shrink?: string | number;

  /* and so on */
}

type FlexItemProps = 
  | FlexItemType & { box: true } & FlexBoxType
  | FlexItemType;

const flexItemStylesGenerator = (args: FlexItemProps) => {
  /* function to generate flex-item styles */

  if(args.box) {
    /* args includes props of FlexBoxType and FlexItemType */
  }
  else {
    /* args includes props of FlexItemType only */
  }

};

我创建了一个函数 flexItemStylesGenerator,它使用传递的参数生成 CSS 样式。如果 box 道具为真,则用户可以指定 FlexItemType 以及 FlexBoxType 道具,否则仅 FlexItemType 道具。

但是,以上类型没有按预期工作

flexItemStylesGenerator({ flex: 1 }); // works properly, as expected
flexItemStylesGenerator({ jusifyContent: 'space-between' }); // gives warning, as expected cannot use FlexBoxType prop without passing box: true.
flexItemStylesGenerator({ flex: 1, justifyContent: 'space-between' }); // no warning, unexpected

那么如何声明 FlexItemProps 类型以便用户只能在 box 属性设置为 true 时传递 FlexBoxType 属性?

1 个答案:

答案 0 :(得分:0)

您应该将 never 类型添加到独占类型。

type Never<T> = {[P in keyof T]?: never}

type FlexItemProps = 
  | FlexItemType & { box: true } & FlexBoxType
  | FlexItemType & Never<FlexBoxType>

Typescript Playground

never 类型将选择退出类型保护。