首页 > 解决方案 > 打字稿既不是,也不是,但不是两个属性

问题描述

我想断言一个类型既不能有,也不能有,但不能同时有一对属性。

以下内容不起作用,尽管我认为它会起作用。显然拥有a: never并且b: never意味着我必须同时提供这两者?

我还尝试使用{}已编译并运行的 NothingANorB 代替,但没有发现我错误地传递了两个选项的第四种情况。

interface JustA {
    a: string;
    b: never;
}

interface JustB {
    a: never;
    b: string;
}

interface NeitherANorB {
    a: never;
    b: never;
}

type NotBothAAndB = JustA | JustB | NeitherANorB;

function testMe(x: NotBothAAndB) {
    console.log(x);
}

testMe({}); // OK
testMe({ a: "HI!" }); // OK
testMe({ b: "SUP?" }); // OK
testMe({ a: "HI!", b: "SUP?" }); // NOT OK

标签: typescript

解决方案


您可以使用{property?: never}{property?: undefined}说属性不应该存在。请注意,即使在前一种情况下,只要属性具有 value ,它就允许存在undefined,因为这正是 Typescript 处理可选属性的方式。所以这应该做你想要的:

type NotBoth =
    | {a: string, b?: never}
    | {a?: never, b: string}
    | {a?: never, b?: never}

// ok
const test1: NotBoth = {a: 'foo'};
const test2: NotBoth = {b: 'bar'};
const test3: NotBoth = {};
// error: 'string' is not assignable to 'undefined'
const testFail: NotBoth = {a: 'foo', b: 'bar'};

游乐场链接

为方便起见,这里有一个辅助类型,用于构造这样的联合,其中最多允许一些属性之一:

// Simplify<T> just makes the resulting types more readable
type Simplify<T> = T extends infer S ? {[K in keyof S]: S[K]} : never
type NoneOf<T> = Simplify<{[K in keyof T]?: never}>
type AtMostOneOf<T> =
    | NoneOf<T>
    | {[K in keyof T]: Simplify<Pick<T, K> & NoneOf<Omit<T, K>>>}[keyof T]

type NotBoth = AtMostOneOf<{a: string, b: string}>

游乐场链接


推荐阅读