typescript - 删除具有相同形状的类型的冗余

标签 typescript

我创建了一个人为的示例( Typescript Playground )来尝试说明我的问题。 foobarbaz 是互斥的。我只是在寻找一种将 XYZ 保留为函数参数类型的解决方案。我已经知道 X 类型可以在这里工作。

type X = { foo: string; bar?: undefined; baz?: undefined }
type Y = { foo?: undefined; bar: string; baz?: undefined }
type Z = { foo?: undefined; bar?: undefined; baz: string; }
type XYZ = X | Y | Z;

function foo(xyz: XYZ): string | undefined {
    return xyz.foo;
}

理想情况下,我只需要定义所需的部分:

type X = { foo: string };
type Y = { bar: string };
type Z = { baz: string };

但是如果没有冗余,我会收到此错误消息:

Property 'foo' does not exist on type 'XYZ'.
  Property 'foo' does not exist on type 'Y'.

我已经尝试过这个,但最终得到的类型看起来像undefined & string:

type XYZ = { foo?: undefined; bar?: undefined; baz?: undefined } & (X | Y | Z);

最佳答案

我认为您正在寻找 & ( intersection type ),而不是 | ( union type ):

type X = { foo: string };
type Y = { bar: string };
type Z = { baz: string };
type XYZ = X & Y & Z;

来自交叉点类型文档:

An intersection type combines multiple types into one. This allows you to add together existing types to get a single type that has all the features you need. For example, Person & Serializable & Loggable is a Person and Serializable and Loggable. That means an object of this type will have all members of all three types.

Working on the playground .


也就是说,如果您说当 foo 存在时,barbaz 必须 未定义,我认为你会坚持使用交集类型,但是你必须在使用它之前告诉 TypeScript 你知道 foo 存在,方法是 type assertion 。否则,它无法知道您正在处理的是 X 而不是 YZ。例如:

type X = { foo: string };
type Y = { bar: string };
type Z = { baz: string };
type XYZ = X | Y | Z;

function foo(xyz: XYZ): string | undefined {
    if ("foo" in xyz) { // Or whatever appropriate check
        return (xyz as X).foo;
    }
    return undefined;
}

On the playground .

我认为没有类型断言就没有办法做到这一点。 (但再说一遍,我不是 Titian Cernicova-Dragomir。:-) )


另一个选择是使用 function overloads ,但您明确表示要保留 XYZ,并且仍然需要您有逻辑来通过类型断言来检测您正在处理的内容。

关于typescript - 删除具有相同形状的类型的冗余,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55168703/

相关文章:

typescript - TS 2540 : Cannot assign to style because it is a read-only property

javascript - 为什么我的 SectionList 有时只呈现一个部分?

html - Angular - 使用 NgStyle 动态更改 CSS 属性

typescript - 使用不是有效变量名称的属性名称进行对象解构

javascript - 如何从 Typescript 上的 FormGroup 中的动态重复表单中获取值?

javascript - VSCode TypeScript Lint

javascript - 如何使用映射过滤嵌套数组并使用对象过滤

javascript - 输入 radio 中的 ngModel?

node.js - 为什么 “require”编译但 “import”不编译?

javascript - 如何将一个对象映射到另一个对象?