如何使用泛型类型访问对象并解决类型检查报错
问题解决方法
错误根源在于TypeScript无法推断this.locators(即ObjType[T][F])必然包含input字段——因为form2.item1没有input属性,当用form2和item1实例化类时,this.locators不存在该字段,导致类型检查不通过。
以下是两种无需额外定义interface/type的解决方式,严格遵循从const obj自动推断类型的要求:
方式一:自定义类型守卫明确类型
添加一个类型守卫函数,帮助TypeScript在编译时识别this.locators是否包含input字段:
const obj = { form1: { item2: { checkbox: 'checkbox', input: 'input', } }, form2: { item1: { checkbox: 'busin' } } }; type ObjType = typeof obj; type ProgramKeys = keyof ObjType; type FormKeys<T extends ProgramKeys> = keyof ObjType[T]; // 自定义类型守卫,判断对象是否包含合法的input字段 function hasInput<T>(obj: T): obj is T & { input: string } { return 'input' in obj && typeof obj.input === 'string'; } class CheckboxFormOne<T extends ProgramKeys, F extends FormKeys<T>> { locators: ObjType[T][F]; constructor(public program: T, public form: F) { this.locators = obj[program][form]; } fillInput(input: keyof ObjType[T][F]) { if (hasInput(this.locators) && input === 'input') { // 此处TypeScript能正确识别this.locators包含input属性 console.log(this.locators.input); } } } new CheckboxFormOne('form1', 'item2').fillInput('input'); // 若尝试调用 new CheckboxFormOne('form2', 'item1').fillInput('input'),TypeScript会直接报错
方式二:给方法添加泛型约束,限制仅合法场景可调用
通过泛型约束,让fillInput方法仅在ObjType[T][F]包含input字段时才能被调用,从根源避免非法调用:
const obj = { form1: { item2: { checkbox: 'checkbox', input: 'input', } }, form2: { item1: { checkbox: 'busin' } } }; type ObjType = typeof obj; type ProgramKeys = keyof ObjType; type FormKeys<T extends ProgramKeys> = keyof ObjType[T]; class CheckboxFormOne<T extends ProgramKeys, F extends FormKeys<T>> { locators: ObjType[T][F]; constructor(public program: T, public form: F) { this.locators = obj[program][form]; } // 泛型约束:仅当input是'input'且属于当前locators的key时,允许调用方法 fillInput<InputKey extends keyof ObjType[T][F]>( input: InputKey extends 'input' ? 'input' : never ) { // 此处TypeScript已能推断this.locators必然包含input属性 console.log(this.locators.input); } } new CheckboxFormOne('form1', 'item2').fillInput('input'); // new CheckboxFormOne('form2', 'item1').fillInput('input') 会直接报错,因为input不是合法参数
核心逻辑说明
- 方式一通过类型守卫在运行时验证属性存在性,同时为TypeScript提供编译时类型提示;
- 方式二通过泛型约束缩小方法的适用范围,直接阻止非法场景的调用,更符合类型安全的设计原则。
内容的提问来源于stack exchange,提问作者Pentium3k
相关产品推荐
相关产品推荐

