reactjstypescript

Cannot set a value for an object of type `React.CSSProperties` with key `keyof React.CSSProperties`


As the title says, the following code raises ts error written in the comment. How can I fix the error without using workaround like any?

import {CSSProperties} from 'react';

const style: CSSProperties = {color: 'blue'}
const merged: CSSProperties = {backgroundColor: 'white'};


let k: keyof CSSProperties;
for (k in merged){
    //  below line raises:
    //  Type 'string | number | (string & {}) | (number & {}) | undefined' is not assignable to type '"-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | undefined'.
    //      Type 'string' is not assignable to type '"-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | undefined'.
    // 
    style[k] = merged[k];
}

ts playground: https://www.typescriptlang.org/play/?ssl=10&ssc=1&pln=10&pc=2#code/JYWwDg9gTgLgBAbwMIGUUAUoTAU1sHAZwF84AzLEOAcihwEMBjGagbgCh3GIA7Q+fgE8ANjgBccVBiy58ROAF5E3YdAnUARsICuOasS69+cEHgDmOACYSpmbHhgFCixBqYBrM1m09LSCKpQ6gDuABbAMHrEHJyi8O4S7jiCEGSSaHayjkQcZNBwABTucMA8JuZWAJQI7HB1cEKiANruALouplAWli2tHMRAA


Solution

  • The problem seems to be that merged[keyof CSSProperties] can take any value that is permissible for any key in CSSProperties. What you want is to somehow narrow down which values you mean. One way to achieve this is using generics:

    import {CSSProperties} from 'react';
    
    const style: CSSProperties = {color: 'blue'}
    const merged: CSSProperties = {backgroundColor: 'white'};
    
    const mergeStyle = <T extends keyof CSSProperties>(style: CSSProperties, key: T, value: CSSProperties[T]): void => {
        style[key] = value;
    };
    
    let k: keyof typeof merged;
    for (k in merged){
        mergeStyle(style, k, merged[k]);
    }
    
    

    This works because it tells TypeScript that the value parameter is actually the correct type for k.