假设我有一个通用实用程序类,它应该与一个类接口,并且有一个方法setPropertiesToTrue,该方法接受类属性列表,并将类实例中的这些属性设置为true。
class SomeObject{
x: boolean
y: boolean
z: string
constructor(x: boolean,y: boolean,z: string){
this.x = x,
this.y = y,
this.z = z
}
}
class ProperySetter<TSomeObject>{
objectContext: TSomeObject
constructor(objectContext: TSomeObject){
this.objectContext = objectContext
}
setPropertiesToTrue(properties: Array<keyof TSomeObject>){
properties.forEach(property => {
this.objectContext[property] = true
})
}
}
const someObject = new SomeObject(false, false, "hello")
const propertySetter = new ProperySetter(someObject);
propertySetter.setPropertiesToTrue(["x", "y"])
console.log(someObject.x) // changed from false to true
console.log(someObject.y) // changed from false to true
console.log(someObject.z) // unchanged
这是一个TS游乐场的例子,或多或少我正在尝试做什么。
在上面的例子中(在操场的第22行(,typescript似乎不知道作为属性传递的键对应于泛型TSomeObject
中的布尔值。所以我得到了错误:
类型"boolean"不可分配给类型"TSomeObject[keyofTSomeObject]'。
这是有意义的,因为keyof TSomeObject
对应于TSomeObject的所有键,而不仅仅是对应于布尔键的键。
有办法绕过这个吗?
您可以加强输入数组的约束,使其仅包含boolean
值的键。然而,TS不够聪明,无法看到知道密钥在数组中是有效的。因此,您只需要执行强制转换即可使代码正常工作。以下是对密钥类型有更好约束的工作代码示例:
class SomeObject{
x: boolean
y: boolean
z: string
constructor(x: boolean, y: boolean, z: string){
this.x = x,
this.y = y,
this.z = z
}
}
class ProperySetter<TSomeObject>{
objectContext: TSomeObject
constructor(objectContext: TSomeObject){
this.objectContext = objectContext
}
setPropertiesToTrue(properties: Array<keyof { [K in keyof TSomeObject as TSomeObject[K] extends boolean ? K : never]: 0 }>){
properties.forEach(property => {
(this.objectContext as any)[property] = true
})
}
}
const someObj = new SomeObject(true, true, "hey");
const setter = new ProperySetter(someObj);
setter.setPropertiesToTrue(["x", "y"])
// @ts-expect-error not a boolean property
setter.setPropertiesToTrue(["z"]);
TypeScript游乐场链接