如何定义TypeScript类型使新对象仅含原对象部分键且值类型不同
问题原因
你对Partial泛型的使用方式有误:Partial<T>的作用是将对象类型T的所有属性转为可选属性,它的泛型入参要求是对象类型,不能作用于键的联合类型。
你之前尝试的Record<Partial<keyof typeof obj>, number>写法中,Partial接收的keyof typeof obj是字符串联合类型,不符合泛型约束,TS会自动忽略该Partial的作用,最终得到的类型仍然要求包含obj的所有属性,因此会报缺失属性的错误。
正确实现方式
写法1:Partial<Record<...>>(推荐)
外层套Partial作用于整个Record对象类型,即可让所有属性变为可选,仅保留你需要的子集即可:
const mapping: Partial<Record<keyof typeof obj, number>> = { a: 10, b: 20 };
类型推导逻辑:
- 先通过
keyof typeof obj获取原对象所有键的联合类型:"a" | "b" | "c" | "d" | "e" | "f" Record<上述联合类型, number>定义的是「包含所有上述键、值为number」的对象类型- 外层
Partial将上述对象类型的所有属性转为可选,你可以任选子集定义,值统一为number类型
写法2:手写映射类型
和上述写法完全等价,你也可以手动写可选属性的映射类型:
const mapping: { [key in keyof typeof obj]?: number } = { a: 10, b: 20 };
写法3:宽松索引签名(仅适用于允许额外键的场景)
如果你不需要严格限制mapping的键只能是原对象的键的子集,可以直接使用字符串索引签名:
const mapping: Record<string, number> = { a: 10, b: 20, // 可以加任意其他字符串键 };
内容的提问来源于stack exchange,提问作者Samuel Neff
相关产品推荐
相关产品推荐

