我需要一种通过类访问 obj 的方法。 我想为此使用通用类型。
问题是在类中我收到错误 - 无法检查 this.locators 是否包含输入字段。
如何解决?我想提一下,类型必须从
const obj
推断出来,我不想定义任何接口/类型。
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];
}
fillInput(input: keyof typeof obj[T][F]) {
if ('input' in this.locators && typeof this.locators[input] === 'string') {
this.locators.input
}
}
}
new CheckboxFormOne('form1', 'item2').fillInput('input')
这是 TypeScript 的一个已知错误或限制,报告于 microsoft/TypeScript#21760。当您开始使用泛型进行多个索引访问时,编译器往往会失去对泛型约束的跟踪,并最终将它们扩大到导致错误的东西。除非这个问题得到解决(这似乎不太可能,或者至少没有迹象表明它正在解决),否则您将需要解决它。
通常,当您知道类型
X
可以分配给类型 Y
但编译器不知道这一点时,您通常可以使用 交集 X & Y
代替 X
。如果您对可分配性的看法是正确的,那么 X & Y
最终将等同于 X
(函数类型有一些例外,但这与这里不直接相关)。但编译器会接受X & Y
可以通过交集的定义分配给Y
。
一种解决方法是将
ObjType[PK][FK]
与 object
相交,以便 TypeScript 允许您使用 in
运算符:
class CheckboxFormOne<PK extends ProgramKeys, FK extends FormKeys<PK>> {
locators: object & ObjType[PK][FK]; // constrain to object
constructor(public program: PK, public form: FK) {
this.locators = obj[program][form]! // assert non-nullish
}
fillInput(input: keyof typeof obj[PK][FK]) {
if ('input' in this.locators && typeof this.locators[input] === 'string') {
this.locators.input
}
}
}
请注意,编译器仍然无法确定
obj[program][form]
是非空的,因此我在那里使用 非空断言运算符 (!
)。
或者你可以做更多的运行时检查来说服 TS
this.locations
是一个对象:
class CheckboxFormOne<PK extends ProgramKeys, FK extends FormKeys<PK>> {
locators: ObjType[PK][FK];
constructor(public program: PK, public form: FK) {
this.locators = obj[program][form];
}
fillInput(input: keyof typeof obj[PK][FK]) {
// do extra runtime tests
if (this.locators && typeof this.locators === "object" &&
'input' in this.locators && typeof this.locators[input] === 'string') {
this.locators.input
}
}
}
其中任何一个都不是特别好,还有其他也不是很好的方法,但重点是你需要以某种方式解决它。