【问题标题】:Typescript not inferring expression signature match打字稿不推断表达式签名匹配
【发布时间】:2019-07-10 05:10:28
【问题描述】:

我一直在使用 Typescript 中的一些通用代数数据类型(v3.5.2 应该是最新的),它似乎无法检测似乎应该能够弄清楚的函数的签名匹配:

  type Success<T> = {          
    tag: 'success';            
    value: T;
    fbind<R, E>(func: (value: T) => Result<R, E>) : Result<R, E>;
  } 

  type Failure<E> = {          
    tag: 'failure';
    error: E;
    fbind<T>(_func: (value: T) => Failure<E>) : Failure<E>;
  }

  type Result<T, E> = Success<T> | Failure<E>;

  function success<T>(value: T) : Success<T> {
    return {
      tag: 'success',
      value,
      fbind<R, E>(func: (value: T) => Result<R, E>): Result<R, E> {
        return func(this.value);
      },
    };
  }

  function failure<E>(error: E) : Failure<E> {
    return {
      tag: 'failure',
      error,
      fbind<T>(_func: (value: T) => Failure<E>) : Failure<E> {
        return this;
      },
    };
  }

  type ValidationError = string;

  function parseDate(value: string) : Result<Date, ValidationError> { 
    // simple example to show issue 
    return success(new Date(value));
  }

  function logDate(date: Date) : Result<Date, ValidationError> {
    console.log('Date: ', date);
    return success(date);
  }

  parseDate('1-1-2019').fbind(logDate);

.fbind 调用logDate 时,它输出以下错误:

Cannot invoke an expression whose type lacks a call signature. Type '(<R, E>(func: (value: Date) => Result<R, E>) => Result<R, E>) | (<T, R>(_func: (value: T) => Result<R, string>) => Result<R, string>)' has no compatible call signatures.

是否有我没有看到的错误?或者,有没有办法为类型系统提供一些帮助,以便它能够弄清楚?

更新

使用以下代码:

type Success<T> = { 
  tag: 'success';
  value: T;
  fbind<R, E>(func: (value: T) => Result<R, E>) : Result<R, E>;
}

type Failure<E> = { 
  tag: 'failure';
  error: E;
  fbind<T, R>(_func: (value: T) => Result<R, E>) : Result<R, E>;
}

type Result<T, E> = Success<T> | Failure<E>;

function success<T>(value: T) : Success<T> { 
  return { 
    tag: 'success',
    value,
    fbind<R, E>(func: (value: T) => Result<R, E>): Result<R, E> { 
      return func(this.value);
    },
  };
}

function failure<E>(error: E) : Failure<E> { 
  return { 
    tag: 'failure',
    error,
    fbind<T, R>(_func: (value: T) => Result<R, E>) : Result<R, E> { 
      return this;
    },
  };
}

type ValidationError = string;

function parseDate(value: string) : Result<Date, ValidationError> { 
  // simple example to show issue
  return success(new Date())
}

function logDate(date: Date) : Result<Date, ValidationError> { 
  console.log('Date: ', date);
  return success(date);
}

parseDate('1-1-2019').fbind(logDate);

.fbind 调用logDate 时,仍然输出以下错误:

Cannot invoke an expression whose type lacks a call signature. Type '(<R, E>(func: (value: Date) => Result<R, E>) => Result<R, E>) | (<T, R>(_func: (value: T) => Result<R, string>) => Result<R, string>)' has no compatible call signatures.

在 typescript repo 上提出问题后,typescript 目前似乎不支持在 3.5.3 及更低版本 (https://github.com/microsoft/TypeScript/issues/32314) 中调用多个通用函数签名的联合。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    如果您将实现分解并使其更宏大,如下所示

    const result = parseDate('1-1-2019');
    if (result.tag === 'success') {
      result.fbind(logDate);
    } else if (result.tag === 'failure') {
      result.fbind(logDate);
    }
    

    你会得到一个更具体的错误

    Argument of type '(date: Date) => Result<Date, string>' is not assignable to parameter of type '(value: Date) => Failure<string>'.
      Type 'Result<Date, string>' is not assignable to type 'Failure<string>'.
        Property 'error' is missing in type 'Success<Date>' but required in type 'Failure<string>'
    

    因此,由于parseDate 返回的是 Success 或 Failure,并且它们的 fbind 的实现都采用不同的回调,因此如果 parseData 返回了 Failure,我们尝试传递 logDate(输出一个成功/失败)到失败的fbind,它只接受一个返回Failure的回调,所以打字稿会抛出一个错误。

    【讨论】:

    • 如果我将 Failure 切换到 fbind&lt;T, R&gt;(_func: (value: T) =&gt; Result&lt;R, E&gt;) : Result&lt;R, E&gt;;,则您发布的条件代码不再有错误,但 parseDate(...).fbind(logDate) 仍然有 no compatible call signatures 错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    相关资源
    最近更新 更多