I am able to define an object key type from a union like:
type Action = 'foo' | 'bar' | 'baz';
type UserStates = 'active' | 'deleted' | 'dishonoured';
type Permission = {
[key in UserStates]: Action[];
};
However, I have a scenario where the options are const literals like:
const UserStates = ['active', 'deleted', 'dishonoured'] as const;
const Action = ['foo', 'bar', 'baz'] as const;
type Permission = {
[key: typeof UserStates[number]]: typeof Action[number][];
};
This results in:
error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.
How should I define the key signature if this scenario?
Working Example for union types:
type Action = 'foo' | 'bar' | 'baz';
type UserStates = 'active' | 'deleted' | 'dishonoured';
type Permission = {
[key in UserStates]: Action[];
};
export const PERMISSIONS: Permission = {
active: ['foo', 'bar', 'baz'],
deleted: ['bar'],
dishonoured: ['baz'],
};
const hasPermission = (userState: UserStates, action: Action): boolean =>
PERMISSIONS[userState].some((x) => x === action);
console.info(hasPermission('active', 'foo'));
console.info(hasPermission('deleted', 'foo'));
CodePudding user response:
A Record instead will work:
type Permission = Record<typeof UserStates[number], typeof Action[number][]>;
This results in the type:
type Permission = {
active: ("foo" | "bar" | "baz")[];
deleted: ("foo" | "bar" | "baz")[];
dishonoured: ("foo" | "bar" | "baz")[];
}
CodePudding user response:
You almost had it:
type Permission = {
[key in typeof UserStates[number]]: typeof Action[number][];
};