I have a nested json object and define a interface for it
interface Menu {
[key: string]: string[] | Menu;
}
const menuOnlyForRoles: Menu = {
site: {
only: [],
category: {
only: ['manager', 'head', 'lead'],
},
'floor-section': {
only: ['head', 'lead'],
},
},
};
But when I use it. It appear a warning.
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[]'
What did I do wrong or missing?
CodePudding user response:
You didn't do anything wrong per se. TypeScript just cannot infer whether your menuPermissionForKey
is a Menu
object or a string
array.
Ideally, you'd define your Menu
type more strictly. Barring that, you can create a type 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 || []
: [];
Alternatively, if you're dealing with static data that is known at compile-time, you can use a const
assertion, optionally with the satisfies
operator to enforce type-checking at edit time:
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 || [];