为什么 typescript 无法正确引用我示例中的类型?

问题描述 投票:0回答:1

考虑如下

Option
ADT 的代码(与
typescript functional-programming option-type functor
1个回答
0
投票

您的代码的一个问题是它不正确,因此编译器实际上根本没有希望正确推断类型。正确的实现如下所示:

const mapOption: MapOption = f => fa => (
  match(
    () => none,
    value => some(f(value)) // error!
    // -----------> ~~~~~
    // Argument of type 'unknown' is not assignable to parameter of type 'A'.
  )
)(fa);

但是,正如您所看到的,推理问题仍然存在。编译器无法从

context
推断 value 的类型,因此它会回退到
unknown
类型

这种事情归根结底是 TypeScript 的设计限制。该语言不能总是推断“通用”类型参数并同时从上下文推断类型。当前关于一般问题的开放问题是 microsoft/TypeScript#47599 虽然多年来这里已经有所改进,但它可能总会以某种形式存在。 TypeScript 不使用

full

unificiation 算法进行类型推断,如其他一些函数式编程语言中那样,以及 microsoft/TypeScript#30134 中的要求。 它可能永远不会使用这样的算法,因为(根据

microsoft/TypeScript#17520 上的评论

),当前的推理算法“具有能够在不完整的代码中进行部分推理的明显优势,这是非常有益的在 IDE 中完成语句。”

如果您希望代码能够编译,我们必须解决这个问题。一种方法是做您不想做的事情:“内联”类型。也许是这样的:

const mapOption: MapOption = f => fa => ( match( () => none, (value: Parameters<typeof f>[0]) => some(f(value)) ) )(fa);

这里我使用 

Parameters 实用程序类型

 来获取与 
A 对应的匿名泛型类型参数的句柄。否则,您必须非常明确地执行此操作并实际声明类型参数:
const mapOption3: MapOption = <A, B>(f: (x: A) => B) => (fa: Option<A>) => (
  match(
    () => none,
    (value: A) => some(f(value))
  )
)(fa);

另一种解决方法是利用一些
无点样式

来消除fa,从而通过缩短预期返回类型和所需输入类型之间的“距离”来使类型推断变得更容易:

const mapOption: MapOption = f => match(
  () => none,
  value => some(f(value))
);

这种方式对于特定的代码示例可能是理想的,但您可能通常需要诉诸于早期的方法之一。如果没有完全统一,您将不得不在某些可能会被推断出的地方指定类型。

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.