Q:

Why is it okay to have a ReactClass props of {} only sometimes?

The following (messy, probably incoherent) Purescript code is a toy Thermite/Websocket script that sends some text to a Websocket when a button is pressed:
module Main where

import Prelude
import React as R
import React.DOM.Props as RP
import ReactDOM as RDOM
import Thermite as T
import Control.Coroutine (cotransform, connect, runProcess, Producer, Consumer, consumer, producer, emit, ($$))
import Control.Coroutine.Aff (produce', produceAff, produce)
import Control.Monad.Aff (launchAff, runAff, Aff)
import Control.Monad.Aff.AVar (AVAR)
import Control.Monad.Aff.Class (liftAff)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Class (liftEff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Control.Monad.Eff.Exception (EXCEPTION)
import Control.Monad.Eff.Var (($=))
import Control.Monad.Writer (lift)
import DOM (DOM) as DOM
import DOM.HTML (window) as DOM
import DOM.HTML.HTMLAnchorElement (download)
import DOM.HTML.Types (htmlDocumentToParentNode) as DOM
import DOM.HTML.Window (document) as DOM
import DOM.Node.ParentNode (querySelector) as DOM
import Data.Either (Either(..))
import Data.Generic (class Generic, gShow)
import Data.Maybe (fromJust, Maybe(..))
import Data.Nullable (toMaybe)
import Partial.Unsafe (unsafePartial)
import React.DOM (text, p', td', input, tr', tbody', th, thead', table, div, h1', button) as R
import Unsafe.Coerce (unsafeCoerce)
import WebSocket (WEBSOCKET, Connection(..), Message(..), URL(..), runMessageEvent, runMessage, newWebSocket)

data Action = SendButtonPress | SetText String

derive instance genericAction :: Generic Action

instance showAction :: Show Action where
  show = gShow

type State = { connection :: Connection
             , someText :: String
             }

initialState :: Connection -> State
initialState socket = { connection: socket
                      , someText: ""
                      }

render :: T.Render State _ Action
render dispatch _ state _ =
  [ R.p' [ R.text "Value: "
         , R.text $ show state.someText
         ]
  , R.p' [ R.input [ RP.placeholder "Enter rubbish here"
                   , RP.onChange \e -> dispatch (SetText (unsafeCoerce e).target.value)
                   ] []
         , R.button [ RP.onClick \_ -> dispatch SendButtonPress ]
                    [ R.text "Send"]
         ]
  ]

performAction :: T.PerformAction _ State _ Action
performAction SendButtonPress _ state        = void $ lift (sendMsg state.someText state.connection)
performAction (SetText s) _ _ = void $ T.cotransform $ _ { someText = s}

sendMsg :: forall a eff. (Show a) => a -> Connection -> Aff (ws :: WEBSOCKET, err :: EXCEPTION | eff) Unit
sendMsg m (Connection s) = liftEff $ s.send (Message (show m))

spec :: T.Spec _ State _ Action
spec = T.simpleSpec performAction render

wsProducer :: forall eff. Connection -> Producer String (Aff (avar :: AVAR, err :: EXCEPTION, ws :: WEBSOCKET | eff)) Unit
wsProducer (Connection s) = produce \emit -> do
  s.onmessage $= \event -> do
    emit $ Left $ runMessage (runMessageEvent event)

wsConsumer :: forall t22 eff t31. (Show t31) => Consumer t31 (Aff ( console :: CONSOLE | eff ) ) t22
wsConsumer = consumer \msg -> do
  liftEff $ log $ show msg
  pure Nothing

main :: Aff (avar :: AVAR, dom :: DOM.DOM, err :: EXCEPTION, ws :: WEBSOCKET, console :: CONSOLE) Unit
main = do
  socket <- liftEff $ newWebSocket (URL "ws://echo.websocket.org") []
  let state = initialState socket
  component <- liftEff (gitItInTheDOM state)
  runProcess (connect (wsProducer socket) (wsConsumer))

gitItInTheDOM :: forall eff props. State -> (Eff (dom :: DOM.DOM | eff) (R.ReactClass props))
gitItInTheDOM state = do
  document <- DOM.window >>= DOM.document
  let aJarOfSomeSort = DOM.querySelector "#container" (DOM.htmlDocumentToParentNode document)
  container <- unsafePartial (fromJust <<< toMaybe <$> aJarOfSomeSort)
  let component = T.createClass spec state
  -- RDOM.render (R.createFactory component {}) container
  pure component

My question is about gitItInTheDOM, when the RDOM.render line is uncommented the code no longer type checks. This is the error message:
Could not match type

    {}                                                                                                          

  with type                                                                                                     

    props1                                                                                                      

while trying to match type ReactClass {}                                                                        
  with type ReactClass props1                                                                                   
while checking that expression (bind ((bind window) document)) (\$4 ->                                          
                                                                  case $4 of                                    
                                                                    document -> ...                             
                                                               )                                                
  has type Eff                                                                                                  
             ( dom :: DOM                                                                                       
             | eff0                                                                                             
             )                                                                                                  
             (ReactClass props1)                                                                                
in value declaration gitItInTheDOM                                                                              

where props1 is a rigid type variable                                                                           
        bound at line 91, column 1 - line 97, column 8                                                          
      eff0 is a rigid type variable                                                                             
        bound at line 91, column 1 - line 97, column 8

Changing gitItInTheDOM to this does type check however:
gitItInTheDOM :: forall eff. State -> Eff (dom :: DOM.DOM | eff) Unit
gitItInTheDOM state = void do
  document <- DOM.window >>= DOM.document
  let aJarOfSomeSort = DOM.querySelector "#container" (DOM.htmlDocumentToParentNode document)
  container <- unsafePartial (fromJust <<< toMaybe <$> aJarOfSomeSort)
  let component = T.createClass spec state
  RDOM.render (R.createFactory component {}) container

But does not return the component, how can it return the component and still type check, please? It seems the type checker will only accept a props parameter of {} for createFactory under certain circumstances, I don't understand what those circumstances are, and why it's not type checking.
The idea of puring the component is to pass back a 'driver' to main, which can then pass it to wsConsumer, making it possible to update the DOM (using Thermite/React) when new messages are received through the WebSocket. I also have no idea if this is a valid way to achieve what I'm trying to do, if this makes no sense: how can it be made valid?

A:

If you change your original type signature to
gitItInTheDOM :: forall eff. State -> (Eff (dom :: DOM.DOM | eff) (R.ReactClass _))

this should typecheck, and tell you the missing type for the wildcard.
Why?
This is about universal quantification. Your original type contains a forall props, so for any type we choose to instantiate for props, the definition of gitItInTheDOM should make sense. In fact your component returned from T.createClass can be given ReactClass props type for any props, as your spec doesn't make use of the props in render or performAction, so this is OK - you can see this by writing out the type for spec explicitly guided by the compiler's complaints about _.
However when you uncomment the line rendering your component, the R.createFactory has been supplied with the value {}, fixing props to a particular type {}, conflicting with your claim that the function works for any type for props.
So you can fix this by either fixing the return type (...R.ReactClass {}) or allow the caller to pass in their choice of props, whatever type that may be.

