在TypeScript中动态分配具有混合类型属性的对象的属性



假设我有一个对象,其某些属性的类型并不完全相同,并且我想为动态标识的属性分配一个动态值。这在JavaScript中工作得很好,但我如何在TypeScript中做到这一点,消除not assignable to type 'never'TS(2322(错误,理想情况下不使用any

示例代码(此处为操场(:

interface Film {
name : string;
durationInSeconds : number;
}
const myFunction = function(
film: Film,
filmPropertyName: keyof Film,
newValue: string | number
) {
let value = film[filmPropertyName];
console.log('Existing value:', value); //value is of type `string | number`, inferred in prior line
//That means that on read, film[filmPropertyName] is of type `string | number` as expected.
//However, on write, it's of type `never.`
film[filmPropertyName] = newValue; //not assignable to type 'never'.ts(2322)
value = newValue; //works just fine with both sides as `string | number`
//Checking that types match seems like a sensible requirement but doesn't help:
if(typeof film[filmPropertyName] === typeof newValue) {
value = newValue; //works fine
film[filmPropertyName] = newValue; //same error as above
}
//even checking that both are a specific standard type doesn't help:
if(typeof film[filmPropertyName] === 'string' && typeof newValue === 'string') {
value = newValue; //works fine
film[filmPropertyName] = newValue; //same error as above
}
}

在这个小例子中,可以建议移除类型混合,例如通过将durationInSeconds设置为string类型并仅将newValue参数的类型更改为string。虽然在这样的一个小例子中这可能是可以的,但在需要其他类型的更复杂的真实代码中它不起作用。

对于遇到此问题的其他人,将film参数的类型更改为any可以满足此错误,但可能会触发其他错误,例如,如果film或其属性在本函数主体期间传递给其他函数。

在赋值之前进行强制转换,例如(film as any)[filmPropertyName] = newValue,会使错误消失,并且可能至少应该在第一个类型检查条件内完成,但似乎放弃了TypeScript的类型检查功能——添加any注释和强制转换看起来真的不像";TypeScript方式"在这种情况下是什么?

解决方案是在这样的类型签名中使用双泛型,保持其他一切不变:

const myFunctionGeneric = function<K extends keyof Film, V extends Film[K]>(
film: Film,
filmPropertyName: K,
newValue: V
) 

修改了这里的操场。

最新更新