如何用TypeScript确保对象的键是另一对象键的子集?
如何确保TypeScript对象的键是另一个对象键的子集?
问题分析
你提供的代码存在两个核心问题:
- 拼写错误:
masterKeyObjects应为masterKeysObject,导致MasterKeys类型被错误推断。 - 数组类型未收窄:
allowedKeys数组未用as const标记,TypeScript会将其推断为MasterKeys[](即所有主键的数组类型),因此Record<typeof allowedKeys[number], string>等价于Record<MasterKeys, string>,要求对象必须包含所有主键,这就是报错的原因。
解决方案
方案1:用as const锁定允许的键数组
通过as const将allowedKeys定义为只读元组,TypeScript会将其元素类型收窄为具体的键值,而非所有主键的联合类型:
export const masterKeysObject = { MAIN: 'main', REDIRECT: 'redirect', DASHBOARD: 'dashboard', USER_ID_PARAM: ':userId', CREATE_NEW: 'create_new' } as const; type MasterKeys = keyof typeof masterKeysObject; // 用as const锁定数组为具体元组,避免类型被拓宽 const allowedKeys = [ 'DASHBOARD', 'CREATE_NEW' ] as const; // 此时typeof allowedKeys[number]是'DASHBOARD' | 'CREATE_NEW' export const onlyAllowedKeysObject: Record<typeof allowedKeys[number], string> = { DASHBOARD: 'Dashboard', CREATE_NEW: 'Create New', };
方案2:直接定义允许的键类型
如果不需要维护allowedKeys数组,可直接定义允许的键类型为MasterKeys的子集:
export const masterKeysObject = { MAIN: 'main', REDIRECT: 'redirect', DASHBOARD: 'dashboard', USER_ID_PARAM: ':userId', CREATE_NEW: 'create_new' } as const; type MasterKeys = keyof typeof masterKeysObject; // 直接指定允许的键为MasterKeys的子集 type AllowedKeys = 'DASHBOARD' | 'CREATE_NEW'; export const onlyAllowedKeysObject: Record<AllowedKeys, string> = { DASHBOARD: 'Dashboard', CREATE_NEW: 'Create New', };
方案3:用工具函数同步数组与类型
若需要动态维护allowedKeys数组,同时确保类型同步,可使用工具函数约束数组元素:
export const masterKeysObject = { MAIN: 'main', REDIRECT: 'redirect', DASHBOARD: 'dashboard', USER_ID_PARAM: ':userId', CREATE_NEW: 'create_new' } as const; type MasterKeys = keyof typeof masterKeysObject; // 工具函数:确保数组元素均为MasterKeys成员,并返回元组类型 const createAllowedKeys = <T extends MasterKeys[]>(keys: [...T]) => keys; const allowedKeys = createAllowedKeys(['DASHBOARD', 'CREATE_NEW']); export const onlyAllowedKeysObject: Record<typeof allowedKeys[number], string> = { DASHBOARD: 'Dashboard', CREATE_NEW: 'Create New', };
内容的提问来源于stack exchange,提问作者HarshvardhanSharma
相关产品推荐
相关产品推荐

