首页 > 解决方案 > 如何正确定义作为其他两种类型的合并交集类型的类型?

问题描述

我试图遵循这个答案,但我不想使用接口。该页面上还有其他几个答案,但没有一个像我的那样设置。

我有以下,

type TMenuOptionBase = {
    id: string;
    text: string;
};
type TMenuOptionRoot = TMenuOptionBase & { onClick: (...params: any[]) => any };
type TMenuOptionParent = TMenuOptionBase & { submenu: TMenuOption[] };

export type TMenuOption = TMenuOptionRoot | TMenuOptionParent;

我可以定义一个对象,例如,

const menuOptions = [
    {
        id: '1',
        text: 'Option 1',
        onClick: () => console.log('clicked 1'),
    },
    {
        id: '2',
        text: 'Option 2',
        submenu: [
            {
                id: '3',
                text: 'Option 3',
                onClick: () => console.log('clicked 3'),
            },
            {
                id: '4',
                text: 'Option 4',
                submenu: [
                    {
                        id: '5',
                        text: 'Option 5',
                        onClick: () => console.log('clicked 5'),
                    },
                ],
            },
        ],
    },
] as TMenuOption[]

此设置的唯一问题是我可以添加一个submenu 一个onClick事件。例如,这不应该有效的,

    {
        id: '1',
        text: 'Option 1',
        onClick: () => console.log('clicked 1'),
        submenu: [ . . . ]
    },

TS 将两者都标识为 type TMenuOption,当它应该分别将它们标识为 typeTMenuOptionParentTMenuOptionRoot时。

我怎样才能让它正常工作?

TS游乐场

我也试过,

type TMenuOptionBase = {
    id: string;
    text: string;
    onClick: (...params: any[]) => any;
    submenu: TMenuOptionBase[];
};

type TMenuOptionParent = Omit<TMenuOptionBase, 'onClick'>;
type TMenuOptionRoot = Omit<TMenuOptionBase, 'submenu'>;

export type TMenuOption = TMenuOptionParent & TMenuOptionRoot;

const menuOption = {
    id: '1',
    text: 'Option 1',
    onClick: () => console.log('s'),
    submenu: []
} as TMenuOption;

但这也没有用。

根据@ford04 的评论,我尝试了 XOR 方法,

type TMenuOptionBase = {
    id: string;
    text: string;
};

type TMenuOption = TMenuOptionBase & (
        | { onClick: (...params: any[]) => void; submenu?: never }
        | { onClick?: never; submenu: TMenuOptionBase[] }
    )

但是当我有 TS 时不会抛出错误,

const menuOption = {
    id: '1',
    text: 'Option 1'
} as TMenuOption

标签: typescript

解决方案


推荐阅读