如何表达取决于其他属性值的函数类型

时间:2020-10-19 16:31:40

标签: typescript

在React项目中,我有一个onChange处理函数,该处理函数带有一个参数。 参数的类型可以是字符串或字符串数​​组,具体取决于另一个布尔属性(multiSelect

我试图这样表达它:

type MultiSelect = {
  multiSelect: boolean;
  onChange: (value: string[]) => void;
};

type SingleSelect = {
  multiSelect?: false;
  onChange: (value: string) => void;
};

type Select = SingleSelect | MultiSelect;

type Props = {otherStuff: string} & Select;

但是打字稿用这种方式说参数的类型是string & string[]并在尝试使用它时给我一个错误:

if (multiSelect) {
   onChange(['a', 'b']);
} else {
   onChange('c');
}

第一个分支出现此错误: 不能将'string []'类型分配给'string&string []'类型。

,第二个分支: 不能将“字符串”类型分配给“字符串和字符串[]”类型。

2 个答案:

答案 0 :(得分:2)

您快到了。将您的Props表示为一个联合,并确保您没有太早地破坏props的结构-如果您破坏props的结构,则不再保留通过使用联合表示的关系。< / p>

一个工作示例:

import * as React from 'react';

type Props = (
  | { multiSelect: true; onChange: (value: string[]) => void }
  | { multiSelect: false; onChange: (value: string) => void }
) & { otherStuff: string };

const MyComponent: React.FunctionComponent<Props> = props => {
  if (props.multiSelect) {
    props.onChange(['foo', 'bar']);
  } else {
    props.onChange('foo')
  }

  return null;
}

答案 1 :(得分:1)

您可以在Typescript中混合使用Conditional typesGenerics来实现您想要的目标

 function onChange<T extends boolean>(input: T extends true ? string[] : string) : any {
        console.log(input)
    }
    
    onChange<true>(['a', 'b'])
    onChange<false>("a")