Here's a simplified version of my code:
// @flow
function a(element: HTMLElement, cssProperty: string, value: string){
element.style[cssProperty] = value;
}
I get the following error:
4: return element.style[cssProperty]
^^^^^^^^^^^ string. This type is incompatible with
4: return element.style[cssProperty]
^^^^^^^^^^^^^^^^^^^^^^^^^^ number
Found 1 error
I'm new to Flow, but experienced in JavaScript... However I can't seem to figure out what I'm doing wrong. I've tried using the type Element as well as HTMLElement but I keep getting an error.
My actual code (not the simplified version above) is a small function that animates elements using CSS transitions:
//window[prop] is used to prevent Closure's dead code removal or mangler from ruining my code
window["animate"] = function(element: HTMLElement, property: string, value: string, time: number): void{
if(element.style.transition){
element.style.transition = property + " " + time+"ms";
}else{
element.style.transition = ", " + property + " " + time+"ms";
}
element.style[property] = value;
setTimeout(function () {
element.style.transition = "";
}, time)
};
If you look at DOM declaration file (https://github.com/facebook/flow/blob/master/lib/dom.js#L1239), you'll see that the style property on HTMLElement is of type CSSStyleDeclaration, which is also defined (https://github.com/facebook/flow/blob/master/lib/cssom.js#L74).
...based on this, this is what I tried, but doesn't work (removed the value function param for simplicity of example)...
// @flow
function a(element: HTMLElement, prop: $Keys<CSSStyleDeclaration>) {
console.log(element.style[prop])
}
If you look at the definition for CSSStyleDeclaration (https://github.com/facebook/flow/blob/master/lib/cssom.js#L376), you'll see that it has a defined object accessor that expects number, not $Keys<CSSStyleDeclaration>.
I know I didn't answer your question, but my understanding is that there is currently no safe way to dynamically mutate this value in Flow or Typescript.
You obviously can do this...
// @flow
function updateBackgroundColor(
element: HTMLElement,
value: $PropertyType<CSSStyleDeclaration, 'backgroundColor'>,
) {
element.style.backgroundColor = value;
}
OR
// @flow
function updateBackgroundColor(
element: HTMLElement,
value: string,
) {
element.style.backgroundColor = value;
}
Running into this issue as well. The hacky workaround I'm using is casting the style object to a regular object:
const nodeStyle: Object = domNode.style;
nodeStyle[prop] = 'hi';
I thought for sure I was doing something wrong (new to Flow; this is the first type I'm adding to this project), but apparently not? Would love to see this fixed!
@joshwcomeau Have you tested that? Because JavaScript should create a copy of the style object instead of a reference, making the change useless.
I haven' tried your code yet, but I think it won't do anything.
Sorry, never mind. Your solution works, thanks!
It works, but you're removing type safety. Object is the same as any, just bound to {}.
One of possible solutions is to use setProperty/getPropertyValue instead of bracket notation. Just beware that this requires hyphenated names (background-color not backgroundColor);
Duplicate of #4014
Most helpful comment
One of possible solutions is to use
setProperty/getPropertyValueinstead of bracket notation. Just beware that this requires hyphenated names (background-colornotbackgroundColor);