Typescript 无法调用其类型在联合类型中缺少调用签名的表达式

Typescript 无法调用其类型在联合类型中缺少调用签名的表达式,typescript,union-types,Typescript,Union Types,我使用TypeScript编写了以下联合类型: interface SingleLineTextFieldPropTypes { multiLine: false; value: string; disabled?: boolean; placeholder?: string; readOnly?: boolean; type?: string; className?: string; onChange: (value: string) => void;

我使用TypeScript编写了以下联合类型:

interface SingleLineTextFieldPropTypes {
  multiLine: false;
  value: string;
  disabled?: boolean;
  placeholder?: string;
  readOnly?: boolean;
  type?: string;
  className?: string;

  onChange: (value: string) => void;
}

interface MultiLineTextFieldPropTypes {
  multiLine: true;
  readOnly?: boolean;
  disabled?: boolean;
  placeholder?: string;
  editorState: EditorState;

  onChange: (editorState: EditorState) => void;
}

type PropTypes =
  SingleLineTextFieldPropTypes |
  MultiLineTextFieldPropTypes;
(这些接口的唯一相关成员是
onChange
函数)

我在React组件中使用它们,如下所示:

class Component extends React.Component<PropTypes> {
  render() {
    if (this.props.multiLine === false) {
      return (
        <input
          type={this.props.type}
          readOnly={this.props.readOnly}
          disabled={this.props.disabled}
          placeholder={this.props.placeholder}
          value={this.props.value}
          onChange={(e: React.FormEvent<HTMLInputElement>) => {
            this.props.onChange((e.target as HTMLInputElement).value as string);
         // ^^^^^^^^^^^^^^^^^^^ here is the error
          }}
          className={classnames('ui-textfield', this.props.className)}
        />
      );
    }
    else { /* ... */ }
  }
}

我该怎么办?关于这个话题,我在StackOverflow上看到了一些其他问题,但没有一个能说明我的情况。谢谢大家!

问题在于
onChange
在两个接口中具有不同的类型,因此生成的类型将是:

onChange: ((value: string) => void) | ((editorState: EditorState) => void)
Typescript不会合并调用签名,因此结果将不可调用。如果两个接口具有相同的签名,则生成的
onChange
将可调用:

interface EditorState { }

interface SingleLineTextFieldPropTypes {
    onChange: (value: EditorState) => void;
}
interface MultiLineTextFieldPropTypes {
    onChange: (editorState: EditorState) => void;
}

type PropTypes  = SingleLineTextFieldPropTypes | MultiLineTextFieldPropTypes;
let d: PropTypes;
d.onChange({}) 
编辑: 问题在于逻辑中有一个字段是
SingleLineTextFieldPropTypes
MultiLineTextFieldPropTypes
,您试图将
onChange
传递给
string
,但
MultiLineTextFieldPropTypes
无法将字符串作为参数处理(至少根据声明)。您可以做以下两件事之一:

  • 更改
    MultilinextFieldPropTypes
    上的定义以允许使用字符串参数:

    interface MultiLineTextFieldPropTypes {
        // onChange has two possible signatures, 
        // note you can't use string|EditorState as that would not get merged.
        onChange: {
            (editorState: string) : void
            (editorState: EditorState) : void
        };
    }
    type PropTypes  = SingleLineTextFieldPropTypes | MultiLineTextFieldPropTypes;
    let editor: PropTypes;
    editor.onChange("") 
    
  • 添加类型保护并传递适当的参数类型:

    if(editor.multiLine === true) {
        let state : EditorState = null; // Get the state
        editor.onChange(state) // TS knows editor is MultiLineTextFieldPropTypes because of the check and the way multiLine  is declared.
    }else {
        let value = "" // Get the simple value
        editor.onChange("")  // editor is SingleLineTextFieldPropTypes
    }
    

  • 问题是,
    onChange
    在两个接口中具有不同的类型,因此生成的类型将是:

    onChange: ((value: string) => void) | ((editorState: EditorState) => void)
    
    Typescript不会合并调用签名,因此结果将不可调用。如果两个接口具有相同的签名,则生成的
    onChange
    将可调用:

    interface EditorState { }
    
    interface SingleLineTextFieldPropTypes {
        onChange: (value: EditorState) => void;
    }
    interface MultiLineTextFieldPropTypes {
        onChange: (editorState: EditorState) => void;
    }
    
    type PropTypes  = SingleLineTextFieldPropTypes | MultiLineTextFieldPropTypes;
    let d: PropTypes;
    d.onChange({}) 
    
    编辑: 问题在于逻辑中有一个字段是
    SingleLineTextFieldPropTypes
    MultiLineTextFieldPropTypes
    ,您试图将
    onChange
    传递给
    string
    ,但
    MultiLineTextFieldPropTypes
    无法将字符串作为参数处理(至少根据声明)。您可以做以下两件事之一:

  • 更改
    MultilinextFieldPropTypes
    上的定义以允许使用字符串参数:

    interface MultiLineTextFieldPropTypes {
        // onChange has two possible signatures, 
        // note you can't use string|EditorState as that would not get merged.
        onChange: {
            (editorState: string) : void
            (editorState: EditorState) : void
        };
    }
    type PropTypes  = SingleLineTextFieldPropTypes | MultiLineTextFieldPropTypes;
    let editor: PropTypes;
    editor.onChange("") 
    
  • 添加类型保护并传递适当的参数类型:

    if(editor.multiLine === true) {
        let state : EditorState = null; // Get the state
        editor.onChange(state) // TS knows editor is MultiLineTextFieldPropTypes because of the check and the way multiLine  is declared.
    }else {
        let value = "" // Get the simple value
        editor.onChange("")  // editor is SingleLineTextFieldPropTypes
    }
    

  • 同样的问题@我不这么认为。在我的例子中,我希望
    PropTypes
    被解析为一个有区别的联合,因为我有
    multiLine
    应该这样做。同样的问题@我不这么认为。在我的例子中,我希望
    PropTypes
    被解析为一个有区别的联合,因为我有
    multiLine
    可以做到这一点。嗨!谢谢你的回答!我已经知道了,但是我想您已经看到了在这些接口中使用与我的代码不同的签名的必要性。你推荐什么?@Victor添加了两种可能的解决方案,而我决定将我的反应成分分成两种。然而,你的解决方案似乎有效,所以我接受这个答案!非常感谢。你好谢谢你的回答!我已经知道了,但是我想您已经看到了在这些接口中使用与我的代码不同的签名的必要性。你推荐什么?@Victor添加了两种可能的解决方案,而我决定将我的反应成分分成两种。然而,你的解决方案似乎有效,所以我接受这个答案!非常感谢。