条件类型打字稿

时间:2021-07-26 15:39:24

标签: typescript

我不知道我是否搜索得很好,但我想做一些类似条件类型的事情。 我想在我的项目中转换这种类型:

type CommonProps = {
    duration: number;
    type?: 'primary' | 'secondary';
    variant?: 'linear' | 'circular' | 'square'
} 

它应该遵循一个原则:如果选择了 primary 类型,则变体可用:'linear' | 'circular' | 'square' 但如果选择了 secondary 类型,变体可用:{{1 }}。

我尝试将其转换为:

'linear' | 'circular'

不幸的是,这不符合预期,因为在代码后面的这种用法存在问题,例如:type CommonProps = { duration: number; }& { type?: 'primary' variant?: 'linear' | 'circular' | 'square' } & { type?: 'secondary'; variant?: 'linear' | 'circular' }

2 个答案:

答案 0 :(得分:2)

我建议使用泛型的另一种解决方案。

type CommonProps<T extends 'primary' | 'secondary'> = {
  duration: number;
  type?: T;
  variant?: T extends 'primary' ? 'linear' | 'circular' | 'square' : T extends 'secondary' ? 'linear' | 'circular' : undefined;
};

const foo: CommonProps<'secondary'> = {
  type: 'secondary',
  variant: 'square' // error square is not part of the variants for secondary
}

答案 1 :(得分:1)

您可以通过区分两种不同类型联合中的 type 属性来解决此问题:

type PrimaryProps = {
    duration: number;
    type?: 'primary';
    variant?: 'linear' | 'circular' | 'square'
}

type SecondaryProps = {
    duration: number;
    type?: 'secondary';
    variant?: 'linear' | 'circular'
}

function foo(a: PrimaryProps | SecondaryProps) {
  switch (a.type) {
    case 'primary':
      a.variant = 'linear';   // fine
      a.variant = 'circular'; // fine
      a.variant = 'square';   // fine
      a.variant = 'pizza';    // fails as expected
      break;
    case 'secondary':
      a.variant = 'linear';   // fine
      a.variant = 'circular'; // fine
      a.variant = 'square';   // fails, can't have square w/secondary
      break;
  }
}

Playground