如何在TypeScript中使用keyof typeof正确定义Record类型?
我定义了一个类枚举风格的TIMEOFDAY对象,尝试基于这些条目创建正确的Record类型:
export const TIMEOFDAY = { FirstLight: 'First Light', Morning: 'Morning', Antemeridiem: 'Antemeridiem', Zenith: 'Zenith', Postmeridiem: 'Postmeridiem', Evening: 'Evening', LastLight: 'Last Light', Night: 'Night', }
但创建Record时TypeScript提示所有键缺失,无法识别通过TIMEOFDAY.FirstLight引用的键,相关代码及错误如下:
type TimeOfDayData = { phase: number hours: number lux: number temperature: number } type TimeOfDayDataRecord = Record<keyof typeof TIMEOFDAY, TimeOfDayData> const TIMEOFDAYDATA: TimeOfDayDataRecord = { [TIMEOFDAY.FirstLight]: /* */ { phase: 1, temperature: 10, hours: 5, lux: 1 }, [TIMEOFDAY.Morning]: /* */ { phase: 2, temperature: 23, hours: 8, lux: 100 }, [TIMEOFDAY.Antemeridiem]: /* */ { phase: 3, temperature: 42, hours: 13, lux: 300 }, [TIMEOFDAY.Zenith]: /* */ { phase: 4, temperature: 55, hours: 16, lux: 500 }, [TIMEOFDAY.Postmeridiem]: /* */ { phase: 3, temperature: 48, hours: 22, lux: 300 }, [TIMEOFDAY.Evening]: /* */ { phase: 2, temperature: 32, hours: 25, lux: 100 }, [TIMEOFDAY.LastLight]: /* */ { phase: 1, temperature: 15, hours: 30, lux: 1 }, [TIMEOFDAY.Night]: /* */ { phase: 0, temperature: -10, hours: 33, lux: 0 }, }
错误信息:Type '{ [x: string]: { phase: number; temperature: number; hours: number; lux: number; }; }' is missing the following properties from type 'TimeOfDayDataRecord': Morning, Antemeridiem, Zenith, Postmeridiem, and 4 more.ts(2740)
keyof typeof TIMEOFDAY获取的是TIMEOFDAY对象的属性名(如FirstLight、Morning这类字符串字面量),但你在TIMEOFDAYDATA中用的是TIMEOFDAY的属性值(如'First Light'、'Morning')作为对象键,两者类型不匹配。TypeScript认为你未提供Record要求的属性名键,反而使用了宽泛的字符串索引,因此报错。
有两种方案可根据需求选择:
方案一:让Record的键匹配TIMEOFDAY的属性值
如果想保持用TIMEOFDAY.FirstLight这类属性值作为对象键,需先固定TIMEOFDAY的类型为字面量类型,再调整Record的键类型:
- 给
TIMEOFDAY添加as const,让TypeScript保留属性值的字面量类型(默认会推断为string):
export const TIMEOFDAY = { FirstLight: 'First Light', Morning: 'Morning', Antemeridiem: 'Antemeridiem', Zenith: 'Zenith', Postmeridiem: 'Postmeridiem', Evening: 'Evening', LastLight: 'Last Light', Night: 'Night', } as const;
- 修改
TimeOfDayDataRecord的键类型为TIMEOFDAY所有属性值的联合类型:
type TimeOfDayDataRecord = Record<typeof TIMEOFDAY[keyof typeof TIMEOFDAY], TimeOfDayData>
此时TIMEOFDAYDATA的定义即可符合类型要求,不再报错。
方案二:改用TIMEOFDAY的属性名作为对象键
如果希望对象键为FirstLight而非'First Light',直接修改TIMEOFDAYDATA的键写法:
const TIMEOFDAYDATA: TimeOfDayDataRecord = { FirstLight: { phase: 1, temperature: 10, hours: 5, lux: 1 }, Morning: { phase: 2, temperature: 23, hours: 8, lux: 100 }, Antemeridiem: { phase: 3, temperature: 42, hours: 13, lux: 300 }, Zenith: { phase: 4, temperature: 55, hours: 16, lux: 500 }, Postmeridiem: { phase: 3, temperature: 48, hours: 22, lux: 300 }, Evening: { phase: 2, temperature: 32, hours: 25, lux: 100 }, LastLight: { phase: 1, temperature: 15, hours: 30, lux: 1 }, Night: { phase: 0, temperature: -10, hours: 33, lux: 0 }, }
这样就能完美匹配Record<keyof typeof TIMEOFDAY, TimeOfDayData>的类型要求。
内容的提问来源于stack exchange,提问作者All Bits Equal

