Typescript:定义JSON嵌套对象

atmip9wb  于 2022-12-24  发布在  TypeScript
关注(0)|答案(1)|浏览(172)

我有一个嵌套的json对象,并为它定义了一个接口

interface Menu {
    [key: string]: string[] | Menu;
}

const menuOnlyForRoles: Menu = {
    site: {
        only: [],
        category: {
            only: ['manager', 'head', 'lead'],
        },
        'floor-section': {
            only: ['head', 'lead'],
        },
    },
};

但是当我使用它的时候。它出现了一个警告。

const menuPermissionForKey = menuOnlyForRoles.site || { only: [] };
const rolesCanAccessMenu= menuPermissionForKey.only || [];
                                               ▔▔▔▔
     any
     Property 'only' does not exist on type 'Menu | string[]'.
       Property 'only' does not exist on type 'string[]'

我做错了什么或遗漏了什么?

yqkkidmi

yqkkidmi1#

你没有做错任何事,TypeScript只是不能推断你的menuPermissionForKey是一个Menu对象还是一个string数组。
理想情况下,您应该更严格地定义Menu类型,除此之外,您可以创建一个类型 predicate :

interface Menu {
    [key: string]: string[] | Menu;
}

const menuOnlyForRoles: Menu = {
    site: {
        only: [],
        category: {
            only: ['manager', 'head', 'lead'],
        },
        'floor-section': {
            only: ['head', 'lead'],
        },
    },
};

function isMenu(data: Menu | string[]): data is Menu {
    return !Array.isArray(data);
}

const menuPermissionForKey = menuOnlyForRoles.site || { only: [] };
const rolesCanAccessMenu= isMenu(menuPermissionForKey)
                              ? menuPermissionForKey.only || []
                              : [];

Playground链接
或者,如果处理的是编译时已知的静态数据,可以使用constAssert,也可以使用satisfies运算符在编辑时强制执行类型检查:

interface Menu {
    [key: string]: readonly string[] | Menu;
}

const menuOnlyForRoles = {
    site: {
        only: [],
        category: {
            only: ['manager', 'head', 'lead'],
        },
        'floor-section': {
            only: ['head', 'lead'],
        },
    },
} as const satisfies Menu;

const menuPermissionForKey = menuOnlyForRoles.site || { only: [] };
const rolesCanAccessMenu = menuPermissionForKey.only || [];

Playground链接

相关问题