Simple code with ts-elmish: a brass tacks explanation

art yerkes
2 min readOct 14, 2021


I wanted to make a vs-code extension that others might not simply rewrite or dismiss when seeing the inside of it not written in a mainstream language, so I was looking for a good elm-like framework. React is close to this but still tragically broken on state, so I wanted something cleaner. ts-elmish seemed the thing.

However I found it worrying that there are no 1-file, simple examples. Nothing really explaining the brass tacks of the typing and actually very permissive typing. You can pass literally anything down the message pipe, but that isn’t a deal breaker for me. At the boundaries I can use diagnostics. I’m much more concerned about making mutable state at least second class if not impossible.

I worked up the absolute simplest (as far as I can tell) example for ts-elmish, cribbed and drastically cut from the examples:

// main.tsx
import * as React from ‘react’
import { render } from ‘react-dom’
import { createElmishComponent } from ‘@ts-elmish/react’// Our callback needs the 'dispatch' function to send a message.
// We'll make our sender functions take it and yield a packaged
// up function that actually sends the message.
// Initially i was expecting callbacks to be wrapped in this kind
// of function automatically, but they aren't.
function sender(dispatch,f) {
return (e) => dispatch(f(e));
// Make a component that does something.
// note: although you control the state (left side of the
// init "tuple"), a "dispatch" function is added to it by the
// framework, thus the state type is Record<String,any>
const App = createElmishComponent({
init: () => [{count: 0}, []],
update: (state, action) => {
// Make a new state without mutation using the message content
// action is the list given below.
return [{
count: state.count + action[0].add
}, []];
view: state => {
return <div>
<h1>Hi there</h1>
<!-- View contains a function sending a message.
-- The function given to sender can use the event
-- argument if it needs.
-- Importantly, message is expected to be enlisted.
<button onClick={sender(state.dispatch, () => [{add:1}])}>
// And use the component!
render(<App />, document.getElementById(‘app’));

I don’t know if there are drawbacks to this minimalist approach apart from anything regarding code organization but hopefully if someone else is interested in ts-elmish, a simple start will be useful where everything needed is visible.