typescript - 联合函数类型的可赋值性规则

标签 typescript

让我们以example为例来自 TS 3.3 文档:

type Fruit = "apple" | "orange";
type Color = "red" | "orange";

type FruitEater = (fruit: Fruit) => number;
type ColorConsumer = (color: Color) => string;

type FnUnion = FruitEater | ColorConsumer

我想,以下函数可以分配给FnUnion :

declare function foo(v: Fruit & Color): number | string

,正如有人告诉我的,函数在参数上是逆变的,在返回类型上是协变的。但请考虑以下内容:

declare let fn: FnUnion
declare function foo(v: Fruit & Color): number | string
declare function foo2(v: Fruit | Color): number
declare function foo3(v: Fruit | Color): string

fn = foo // error, why?
fn = foo2 // works
fn = foo3 // works

我对上述情况下联合函数的一般可分配性规则感兴趣。 foo2foo3 可分配给 fn。但为什么 foo 不可赋值呢?

我肯定会错过一些 TS 知识,感谢您的解答。谢谢! PS:这是一个sample .

最佳答案

需要明确的是,& 是交集,| 是并集。这意味着:

Fruit & Color //=> "orange"
Fruit | Color //=> "apple" | "orange" | "red"

这意味着:

type FnUnion = FruitEater | ColorConsumer

是接受所有水果的函数,或者是接受所有颜色的函数。

以下是该类型的有效用法:

const colorFn: FnUnion = (color: Color) => 'a color'
colorFn('red')
colorFn('orange')

const fruitFn: FnUnion = (fruit: Fruit) => 123
fruitFn('apple')
fruitFn('orange')

注意:必须是其中之一。它必须接受所有水果它必须接受所有颜色。

但是,Fruit & Color 类型只能是'orange'。因此,您将一个只能接受 'orange' 的函数分配给一个允许接受 'orange'|'red''橙色'|'苹果'。这意味着 'red''apple' 永远不能作为参数传递,其中 FnUnion 表示应允许其中之一.

因此 typescript 正确地提示类型不兼容。


此外,Typescript 知道联合体类型,还知道控制流中某些点的联合体成员的值。

当您像这样转换到 FnUnion 时:

const colorFn = ((color: Color) => 'a color') as FnUnion

您告诉 TS 它是联合体的哪个成员是不可知的,因为它不能再根据参数类型进行区分。

因此,似乎唯一安全的推论是这两种类型共有的一个参数。我意识到,这正是它不允许您直接分配的函数类型。

但我认为关键的区别是知道你的函数是工会的哪个成员。

// member known: ColorConsumer
const colorFn: FnUnion = (color: Color) => 'a color'

// member known: FruitEater
const fruitFn: FnUnion = (fruit: Fruit) => 123

// member unknown due to cast to less specific type.
//   only common arguments are allowed,
//   and only return types for those common arguments
const unknownFn: FnUnion = ((some: 'orange') => 'unknown') as FnUnion

// type is concretely known, but is not a match to any member.
const invalidFn: FnUnion = (some: 'orange') => 'invalid'
// ^ type error

FnUnion 表示它是其中之一,如果它不知道是哪一个,那么它是两者的交集。您想说的类型是已知的,它不是成员,而是两者的交集。这就是不兼容的地方。

但是正如您发现的那样,使用 as FnUnion 您可以使 typescript 忘记它对类型转换的了解。

所有这些意味着推断的某物类型并不总是它可以分配的类型。

关于typescript - 联合函数类型的可赋值性规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60440070/

相关文章:

javascript - 将 rxjs 5 重构为 rxjs 6 代码 - retryWhen

angular - 使用 NgRX 实体规范化 Api 响应

javascript - 如何在 HTML 中获取输入类型 Date 并在 angular7 component.ts 文件中使用?

visual-studio - 是否可以在 Visual Studio 中为 TypeScript 方法/类生成注释?

typescript - 当存在类型检查问题时,来自 node_modules 的 tsc 不会抛出控制台异常

javascript - Monaco Editor : Update Cursor position on text inserted

typescript - vuejs typescript 属性路由器不存在

javascript - 错误类型错误 : Cannot read property 'list' of undefined

javascript - 如何检测 View 元素何时在 Angular 中呈现?

javascript - 如果 .ts 文件在文件夹中更深, typescript 无法找到要 bcrypt 的模块