如何在Typescript中使用泛型动态设置特定类型的值



假设我有一个通用实用程序类,它应该与一个类接口,并且有一个方法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游乐场链接

最新更新