Repository navigation
Merge props / wrap components #23
Copy link
Copy link
Open
Description
Hi, 👋
This is more of a PureScript question than anything else, but still figured this is the best place to make it
How can I merge props like in js?
function Loading (extras) {
return (<Video autoPlay {...extras} />)
}but in PS
mkLoading
:: forall attrs attrs_
. Union attrs attrs_ Props_video
=> Effect (Record attrs -> React.JSX)
mkLoading = do
React.component "Loading" \extras -> React.do
pure
( DOM.video
( merge extras
{ autoPlay: true
, loop: true
, muted: true
, playsInline: true
, height: "24"
, className: "loading"
, children:
[ DOM.source
{ type: "video/webm"
, src: "./assets/loader.webm"
}
, DOM.source
{ type: "video/mp4"
, src: "./assets/loader.mp4"
}
]
}
)
)This is a type error
No type class instance was found for
Prim.Row.Union t0
t1
( _aria :: Object String
, _data :: Object String
, about :: String
, acceptCharset :: String
, accessKey :: String
, allowFullScreen :: Boolean
, allowTransparency :: Boolean
, autoFocus :: Boolean
, autoPlay :: Boolean
, capture :: Boolean
, cellPadding :: String
, cellSpacing :: String
, charSet :: String
, children :: Array JSX
, classID :: String
, className :: String
, colSpan :: Int
, contentEditable :: Boolean
, contextMenu :: String
, controls :: Boolean
, crossOrigin :: String
, dangerouslySetInnerHTML :: { __html :: String
}
, datatype :: String
, dateTime :: String
, dir :: String
, draggable :: Boolean
, encType :: String
, formAction :: String
, formEncType :: String
, formMethod :: String
, formNoValidate :: Boolean
, formTarget :: String
, frameBorder :: String
, height :: String
, hidden :: Boolean
, hrefLang :: String
, htmlFor :: String
, httpEquiv :: String
, icon :: String
, id :: String
, inlist :: String
, inputMode :: String
, is :: String
, itemID :: String
, itemProp :: String
, itemRef :: String
, itemScope :: Boolean
, itemType :: String
, key :: String
, keyParams :: String
, keyType :: String
, lang :: String
, loop :: Boolean
, marginHeight :: String
, marginWidth :: String
, maxLength :: Int
, mediaGroup :: String
, minLength :: Int
, muted :: Boolean
, noValidate :: Boolean
, onAbort :: EffectFn1 SyntheticEvent Unit
, onAnimationEnd :: EffectFn1 SyntheticEvent Unit
, onAnimationIteration :: EffectFn1 SyntheticEvent Unit
, onAnimationStart :: EffectFn1 SyntheticEvent Unit
, onBlur :: EffectFn1 SyntheticEvent Unit
, onCanPlay :: EffectFn1 SyntheticEvent Unit
, onCanPlayThrough :: EffectFn1 SyntheticEvent Unit
, onClick :: EffectFn1 SyntheticEvent Unit
, onCompositionEnd :: EffectFn1 SyntheticEvent Unit
, onCompositionStart :: EffectFn1 SyntheticEvent Unit
, onCompositionUpdate :: EffectFn1 SyntheticEvent Unit
, onContextMenu :: EffectFn1 SyntheticEvent Unit
, onCopy :: EffectFn1 SyntheticEvent Unit
, onCut :: EffectFn1 SyntheticEvent Unit
, onDoubleClick :: EffectFn1 SyntheticEvent Unit
, onDrag :: EffectFn1 SyntheticEvent Unit
, onDragEnd :: EffectFn1 SyntheticEvent Unit
, onDragEnter :: EffectFn1 SyntheticEvent Unit
, onDragExit :: EffectFn1 SyntheticEvent Unit
, onDragLeave :: EffectFn1 SyntheticEvent Unit
, onDragOver :: EffectFn1 SyntheticEvent Unit
, onDragStart :: EffectFn1 SyntheticEvent Unit
, onDrop :: EffectFn1 SyntheticEvent Unit
, onDurationChange :: EffectFn1 SyntheticEvent Unit
, onEmptied :: EffectFn1 SyntheticEvent Unit
, onEncrypted :: EffectFn1 SyntheticEvent Unit
, onEnded :: EffectFn1 SyntheticEvent Unit
, onError :: EffectFn1 SyntheticEvent Unit
, onFocus :: EffectFn1 SyntheticEvent Unit
, onGotPointerCapture :: EffectFn1 SyntheticEvent Unit
, onInvalid :: EffectFn1 SyntheticEvent Unit
, onKeyDown :: EffectFn1 SyntheticEvent Unit
, onKeyPress :: EffectFn1 SyntheticEvent Unit
, onKeyUp :: EffectFn1 SyntheticEvent Unit
, onLoadStart :: EffectFn1 SyntheticEvent Unit
, onLoadedData :: EffectFn1 SyntheticEvent Unit
, onLoadedMetadata :: EffectFn1 SyntheticEvent Unit
, onLostPointerCapture :: EffectFn1 SyntheticEvent Unit
, onMouseDown :: EffectFn1 SyntheticEvent Unit
, onMouseEnter :: EffectFn1 SyntheticEvent Unit
, onMouseLeave :: EffectFn1 SyntheticEvent Unit
, onMouseMove :: EffectFn1 SyntheticEvent Unit
, onMouseOut :: EffectFn1 SyntheticEvent Unit
, onMouseOver :: EffectFn1 SyntheticEvent Unit
, onMouseUp :: EffectFn1 SyntheticEvent Unit
, onPaste :: EffectFn1 SyntheticEvent Unit
, onPause :: EffectFn1 SyntheticEvent Unit
, onPlay :: EffectFn1 SyntheticEvent Unit
, onPlaying :: EffectFn1 SyntheticEvent Unit
, onPointerCancel :: EffectFn1 SyntheticEvent Unit
, onPointerDown :: EffectFn1 SyntheticEvent Unit
, onPointerEnter :: EffectFn1 SyntheticEvent Unit
, onPointerLeave :: EffectFn1 SyntheticEvent Unit
, onPointerMove :: EffectFn1 SyntheticEvent Unit
, onPointerOut :: EffectFn1 SyntheticEvent Unit
, onPointerOver :: EffectFn1 SyntheticEvent Unit
, onPointerUp :: EffectFn1 SyntheticEvent Unit
, onProgress :: EffectFn1 SyntheticEvent Unit
, onRateChange :: EffectFn1 SyntheticEvent Unit
, onScroll :: EffectFn1 SyntheticEvent Unit
, onSeeked :: EffectFn1 SyntheticEvent Unit
, onSeeking :: EffectFn1 SyntheticEvent Unit
, onSelect :: EffectFn1 SyntheticEvent Unit
, onStalled :: EffectFn1 SyntheticEvent Unit
, onSubmit :: EffectFn1 SyntheticEvent Unit
, onSuspend :: EffectFn1 SyntheticEvent Unit
, onTimeUpdate :: EffectFn1 SyntheticEvent Unit
, onTouchCancel :: EffectFn1 SyntheticEvent Unit
, onTouchEnd :: EffectFn1 SyntheticEvent Unit
, onTouchMove :: EffectFn1 SyntheticEvent Unit
, onTouchStart :: EffectFn1 SyntheticEvent Unit
, onTransitionEnd :: EffectFn1 SyntheticEvent Unit
, onVolumeChange :: EffectFn1 SyntheticEvent Unit
, onWaiting :: EffectFn1 SyntheticEvent Unit
, onWheel :: EffectFn1 SyntheticEvent Unit
, playsInline :: Boolean
, poster :: String
, prefix :: String
, preload :: String
, property :: String
, radioGroup :: String
, readOnly :: Boolean
, ref :: Ref (Nullable Node)
, resource :: String
, role :: String
, rowSpan :: Int
, scoped :: Boolean
, seamless :: Boolean
, security :: String
, slot :: String
, spellCheck :: Boolean
, src :: String
, srcDoc :: JSX
, srcLang :: String
, srcSet :: String
, style :: CSS
, suppressContentEditableWarning :: Boolean
, tabIndex :: Int
, title :: String
, typeof :: String
, unselectable :: Boolean
, useMap :: String
, vocab :: String
, width :: String
, wmode :: String
)
while applying a function video
of type Union @Type t0 t1
( _aria :: Object String
, _data :: Object String
, about :: String
, acceptCharset :: String
, accessKey :: String
, allowFullScreen :: Boolean
, allowTransparency :: Boolean
, autoFocus :: Boolean
, autoPlay :: Boolean
, capture :: Boolean
, cellPadding :: String
, cellSpacing :: String
, charSet :: String
, children :: Array JSX
, classID :: String
, className :: String
, colSpan :: Int
, contentEditable :: Boolean
, contextMenu :: String
, controls :: Boolean
, crossOrigin :: String
, dangerouslySetInnerHTML :: { __html :: String
}
, datatype :: String
, dateTime :: String
, dir :: String
, draggable :: Boolean
, encType :: String
, formAction :: String
, formEncType :: String
, formMethod :: String
, formNoValidate :: Boolean
, formTarget :: String
, frameBorder :: String
, height :: String
, hidden :: Boolean
, hrefLang :: String
, htmlFor :: String
, httpEquiv :: String
, icon :: String
, id :: String
, inlist :: String
, inputMode :: String
, is :: String
, itemID :: String
, itemProp :: String
, itemRef :: String
, itemScope :: Boolean
, itemType :: String
, key :: String
, keyParams :: String
, keyType :: String
, lang :: String
, loop :: Boolean
, marginHeight :: String
, marginWidth :: String
, maxLength :: Int
, mediaGroup :: String
, minLength :: Int
, muted :: Boolean
, noValidate :: Boolean
, onAbort :: EffectFn1 SyntheticEvent Unit
, onAnimationEnd :: EffectFn1 SyntheticEvent Unit
, onAnimationIteration :: EffectFn1 SyntheticEvent Unit
, onAnimationStart :: EffectFn1 SyntheticEvent Unit
, onBlur :: EffectFn1 SyntheticEvent Unit
, onCanPlay :: EffectFn1 SyntheticEvent Unit
, onCanPlayThrough :: EffectFn1 SyntheticEvent Unit
, onClick :: EffectFn1 SyntheticEvent Unit
, onCompositionEnd :: EffectFn1 SyntheticEvent Unit
, onCompositionStart :: EffectFn1 SyntheticEvent Unit
, onCompositionUpdate :: EffectFn1 SyntheticEvent Unit
, onContextMenu :: EffectFn1 SyntheticEvent Unit
, onCopy :: EffectFn1 SyntheticEvent Unit
, onCut :: EffectFn1 SyntheticEvent Unit
, onDoubleClick :: EffectFn1 SyntheticEvent Unit
, onDrag :: EffectFn1 SyntheticEvent Unit
, onDragEnd :: EffectFn1 SyntheticEvent Unit
, onDragEnter :: EffectFn1 SyntheticEvent Unit
, onDragExit :: EffectFn1 SyntheticEvent Unit
, onDragLeave :: EffectFn1 SyntheticEvent Unit
, onDragOver :: EffectFn1 SyntheticEvent Unit
, onDragStart :: EffectFn1 SyntheticEvent Unit
, onDrop :: EffectFn1 SyntheticEvent Unit
, onDurationChange :: EffectFn1 SyntheticEvent Unit
, onEmptied :: EffectFn1 SyntheticEvent Unit
, onEncrypted :: EffectFn1 SyntheticEvent Unit
, onEnded :: EffectFn1 SyntheticEvent Unit
, onError :: EffectFn1 SyntheticEvent Unit
, onFocus :: EffectFn1 SyntheticEvent Unit
, onGotPointerCapture :: EffectFn1 SyntheticEvent Unit
, onInvalid :: EffectFn1 SyntheticEvent Unit
, onKeyDown :: EffectFn1 SyntheticEvent Unit
, onKeyPress :: EffectFn1 SyntheticEvent Unit
, onKeyUp :: EffectFn1 SyntheticEvent Unit
, onLoadStart :: EffectFn1 SyntheticEvent Unit
, onLoadedData :: EffectFn1 SyntheticEvent Unit
, onLoadedMetadata :: EffectFn1 SyntheticEvent Unit
, onLostPointerCapture :: EffectFn1 SyntheticEvent Unit
, onMouseDown :: EffectFn1 SyntheticEvent Unit
, onMouseEnter :: EffectFn1 SyntheticEvent Unit
, onMouseLeave :: EffectFn1 SyntheticEvent Unit
, onMouseMove :: EffectFn1 SyntheticEvent Unit
, onMouseOut :: EffectFn1 SyntheticEvent Unit
, onMouseOver :: EffectFn1 SyntheticEvent Unit
, onMouseUp :: EffectFn1 SyntheticEvent Unit
, onPaste :: EffectFn1 SyntheticEvent Unit
, onPause :: EffectFn1 SyntheticEvent Unit
, onPlay :: EffectFn1 SyntheticEvent Unit
, onPlaying :: EffectFn1 SyntheticEvent Unit
, onPointerCancel :: EffectFn1 SyntheticEvent Unit
, onPointerDown :: EffectFn1 SyntheticEvent Unit
, onPointerEnter :: EffectFn1 SyntheticEvent Unit
, onPointerLeave :: EffectFn1 SyntheticEvent Unit
, onPointerMove :: EffectFn1 SyntheticEvent Unit
, onPointerOut :: EffectFn1 SyntheticEvent Unit
, onPointerOver :: EffectFn1 SyntheticEvent Unit
, onPointerUp :: EffectFn1 SyntheticEvent Unit
, onProgress :: EffectFn1 SyntheticEvent Unit
, onRateChange :: EffectFn1 SyntheticEvent Unit
, onScroll :: EffectFn1 SyntheticEvent Unit
, onSeeked :: EffectFn1 SyntheticEvent Unit
, onSeeking :: EffectFn1 SyntheticEvent Unit
, onSelect :: EffectFn1 SyntheticEvent Unit
, onStalled :: EffectFn1 SyntheticEvent Unit
, onSubmit :: EffectFn1 SyntheticEvent Unit
, onSuspend :: EffectFn1 SyntheticEvent Unit
, onTimeUpdate :: EffectFn1 SyntheticEvent Unit
, onTouchCancel :: EffectFn1 SyntheticEvent Unit
, onTouchEnd :: EffectFn1 SyntheticEvent Unit
, onTouchMove :: EffectFn1 SyntheticEvent Unit
, onTouchStart :: EffectFn1 SyntheticEvent Unit
, onTransitionEnd :: EffectFn1 SyntheticEvent Unit
, onVolumeChange :: EffectFn1 SyntheticEvent Unit
, onWaiting :: EffectFn1 SyntheticEvent Unit
, onWheel :: EffectFn1 SyntheticEvent Unit
, playsInline :: Boolean
, poster :: String
, prefix :: String
, preload :: String
, property :: String
, radioGroup :: String
, readOnly :: Boolean
, ref :: Ref (Nullable Node)
, resource :: String
, role :: String
, rowSpan :: Int
, scoped :: Boolean
, seamless :: Boolean
, security :: String
, slot :: String
, spellCheck :: Boolean
, src :: String
, srcDoc :: JSX
, srcLang :: String
, srcSet :: String
, style :: CSS
, suppressContentEditableWarning :: Boolean
, tabIndex :: Int
, title :: String
, typeof :: String
, unselectable :: Boolean
, useMap :: String
, vocab :: String
, width :: String
, wmode :: String
)
=> Record t0 -> JSX
to argument (merge extras) { autoPlay: true
, loop: true
, muted: true
, playsInline: true
, height: "24"
, className: "loading"
, children: [ ...
, ...
]
}
while inferring the type of video ((merge extras) { autoPlay: ...
, loop: ...
, muted: ...
, playsInline: ...
, height: ...
, className: ...
, children: ...
}
)
in value declaration mkLoading
where t0 is an unknown type
t1 is an unknown type
PureScript(NoInstanceFound)
Thank a lot for your time and this lib ✨
Reacted by Paul Young
Metadata
Metadata
Assignees
Labels
No labels
Activity
[-]Merge props [/-][+]Merge props / wrap components[/+]maddie927 commentedon Jan 6, 2022
The way Union is used in the DOM modules is a little bit of a hack which could make this difficult to do. Essentially, it leaves one of the two inputs to Union completely unused, so the compiler is free to assume anything it wants to about it. This works in the DOM module where the implementation is in FFI, but that argument is completely unusable within PureScript.
You could maybe accomplish this with an unsafeCoerce though.. maybe in your call to
mergeyou canmerge (unsafeCoerce extras) ...? I'm not on a computer where I can easily play with it at the moment.paulyoung commentedon Apr 24, 2022
I just ran into this. Did anyone find a better way?
pete-murphy commentedon Apr 24, 2022
This is what I get after cleaning up the inferred type for @codingedgar's original example. It seems to work as intended without needing
unsafeCoerce, though I can't say I fully understand the row type constraints 😅 Try PureScript example herepete-murphy commentedon Apr 25, 2022
Maybe another option, if you don't want to declare the
DefaultAttrstype (and don't mind the compiler warning about the missing type annotation onmkLoading):