如何让Record<string, keyof T>在T新增属性时触发编译错误?
解决方案
要让StringToKey在Person类新增属性时触发编译错误,核心是给它加上必须覆盖所有Person属性键的类型约束——当前的Record<string, keyof Person>仅要求值属于Person的键,但不强制包含所有键,所以新增属性时不会报错。
下面提供两种可行方案:
方案1:值联合类型严格匹配(兼容TS 4.5+)
通过类型约束确保StringToKey的值的联合类型与keyof Person完全一致,少任何一个键都会触发报错:
class Person{ public Name: string = ''; public Age: number = 0; } // 辅助类型:提取对象值的联合类型 type ExtractValues<T> = T[keyof T]; class Some { // 约束:值的联合类型必须严格等于keyof Person public StringToKey: Record<string, keyof Person> & ( keyof Person extends ExtractValues<typeof StringToKey> ? ExtractValues<typeof StringToKey> extends keyof Person ? unknown : never : never ) = { "N": "Name", "A": "Age" }; public KeyToVal: {[Key in keyof Person]: (value:string)=>Person[Key]} = { Name: (value: string) => value, Age: (value: string) => Number(value) }; }
当给Person新增属性(比如Gender)后,ExtractValues<typeof StringToKey>的结果("Name" | "Age")会与keyof Person("Name" | "Age" | "Gender")不匹配,编译器直接报错。
方案2:使用satisfies运算符(TS 4.9+推荐)
satisfies能在保留类型推断的同时给对象加额外约束,写法更简洁:
class Person{ public Name: string = ''; public Age: number = 0; } type ExtractValues<T> = T[keyof T]; class Some { public StringToKey = { "N": "Name", "A": "Age" } satisfies Record<string, keyof Person> & ( keyof Person extends ExtractValues<typeof StringToKey> ? unknown : never ); public KeyToVal: {[Key in keyof Person]: (value:string)=>Person[Key]} = { Name: (value: string) => value, Age: (value: string) => Number(value) }; }
原理说明
两种方案都是通过类型约束,强制StringToKey的值必须覆盖所有Person的属性键,一旦Person新增属性,StringToKey的值集合就会缺失对应的键,从而触发编译错误,和KeyToVal的报错逻辑保持一致。
内容的提问来源于stack exchange,提问作者MikHail
相关产品推荐
相关产品推荐

