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

时间:2018-01-02 19:58:39

标签: typescript union-types

我有以下用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 { /* ... */ }
  }
}

现在我收到有关onChange电话的错误:

TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((value: string) => void) | ((editorState: EditorState) => void)' has no compatible call signatures.

我该怎么办?我在StackOverflow上看到了关于这个主题的一些其他问题,但是它们都没有说明我的情况。谢谢!

1 个答案:

答案 0 :(得分:2)

问题是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({}) 

修改 问题出在您的逻辑中,您有一个SingleLineTextFieldPropTypesMultiLineTextFieldPropTypes的字段,并且您尝试传递给onChange string,但MultiLineTextFieldPropTypes可以&# 39; t处理字符串作为参数(至少根据声明)。你可以做以下两件事之一:

  1. 更改MultiLineTextFieldPropTypes上的定义以允许字符串参数:

    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("") 
    
  2. 添加类型保护并传递适当的参数类型:

    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
    }