Static Typing:
Which Language to Choose?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
whoami?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068348/me.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068360/60-606593_icons-clipart-twitter-twitter-logo-png-transparent-png.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068368/github-image.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
- What is Hasura?
- Why do we want static typing?
- A walk through ReasonML, PureScript, TypeScript, and Elm.
- Comparison
- What did we choose and what's the plan?
Agenda
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
What is Hasura?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7152090/hasuraGif.gif)
Why do we want
static typing?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7123542/js.png)
JavaScript is not enough
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
null > 0; // false
null == 0; // false
null >= 0; // true
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7162938/what-should-i-draw-on-this-box-undefined-cannot-read-41323777.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7162940/Screenshot_2020-03-11_at_23.40.57.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7162941/Screenshot_2020-03-11_at_23.40.39.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7162944/Screenshot_2020-03-11_at_23.40.21.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7162946/Screenshot_2020-03-11_at_23.39.38.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7162948/Screenshot_2020-03-11_at_23.39.29.png)
😱
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7277037/Screenshot_2020-04-20_at_17.41.38.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7277041/Screenshot_2020-04-20_at_17.41.14.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7277046/undefined2.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Dynamic typing is not enough
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7131392/2uxj8u6yx9121.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Dynamic typing is great for fast prototyping, testing ideas, but...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
...as a project grows, it's not enough anymore.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7158513/Screenshot_2020-03-10_at_22.26.12.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7132321/Screenshot_2020-03-03_at_17.36.57.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
At some point, control becomes crucial.
Ease of refactoring in a big codebase
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7132425/refactoring.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7158526/Screenshot_2020-03-10_at_22.29.18.png)
Easier onboarding
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7132474/Screenshot_2020-03-03_at_18.12.13.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Easier onboarding
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
- What arguments does it accept?
- What value does it return?
- What external data does it require?
Our backend is written in Haskell
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7158587/Screenshot_2020-03-10_at_22.36.34.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
JavaScript as a build target
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
A walk through: ReasonML, PureScript, TypeScript, and Elm
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Why these four options?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335683/Elm_logo.svg.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335687/1_0ei2MOQxAzF7krm-v60wnQ.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335691/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335696/PureScript_Logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068360/60-606593_icons-clipart-twitter-twitter-logo-png-transparent-png.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
import React, { useState } from "react";
export const Form = () => {
const [name, setName] = useState("");
const [password, setPassword] = useState("");
const onNameChange = e => {
setName(e.target.value);
};
const onPasswordChange = e => {
setPassword(e.target.value);
};
return (
<form>
<input
type="text"
placeholder="Name"
value={name}
onChange={onNameChange}
/>
<input
type="text"
placeholder="Password"
value={password}
onChange={onPasswordChange}
/>
<button type="submit" onSubmit={handleSubmit}>
Submit
</button>
</form>
);
};
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7169142/Screenshot_2020-03-13_at_22.40.56.png)
Login form example
ReasonML
- Rock solid type system and strong type inference.
- Immutable and functional by default, but it supports mutations and side-effects.
- Reason supports React with ReasonReact and JSX syntax.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
[@react.component]
let make = () => {
let (name, setName) = React.useState(() => "");
let (password, setPassword) = React.useState(() => "");
let onNameChange = (e: ReactEvent.Form.t): unit => {
let value = e->ReactEvent.Form.target##value;
setName(value);
};
let onPasswordChange = (e: ReactEvent.Form.t): unit => {
let value = e->ReactEvent.Form.target##value;
setPassword(value);
};
<form>
<input
type_="text"
name="name"
value=name
onChange=onNameChange
placeholder="Name"
/>
<input
type_="password"
name="name"
value=password
onChange=onPasswordChange
placeholder="Password"
/>
<button type_="submit"> {React.string("Submit")} </button>
</form>;
};
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7169142/Screenshot_2020-03-13_at_22.40.56.png)
PureScript
- PureScript has a decent ecosystem.
- Great type system; provides features such as: typeclasses, higher kinded types, row polymorphism, higher-rank types, and many more.
- It's a purely functional and strict language.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
module Form where
import Prelude
import Data.Maybe (fromMaybe)
import Effect (Effect)
import React.Basic.DOM as R
import React.Basic.DOM.Events (targetValue)
import React.Basic.Events (handler)
import React.Basic.Hooks (ReactComponent, component, useState, (/\))
import React.Basic.Hooks as React
form :: Effect (ReactComponent {})
form = do
component "form" \_ -> React.do
{ name } /\ setName <- useState { name: "" }
{ password } /\ setPassword <- useState { password: "" }
pure
$ R.form_
[ R.input
{ onChange:
handler targetValue \value ->
setName \_ -> { name: fromMaybe "" value }
, value: name
, placeholder: "Name"
}
, R.input
{ onChange:
handler targetValue \value ->
setPassword \_ -> { password: fromMaybe "" value }
, value: password
, placeholder: "Password"
}
, R.button
{ type: "submit"
, children: [ R.text "Submit" ]
}
]
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7169142/Screenshot_2020-03-13_at_22.40.56.png)
TypeScript
- Superset of JavaScript
- Optional static typing
- There are many ways to adopt TypeScript.
- Zero configuration support in many modern IDEs.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
import * as React from 'react';
export const Form: React.FC = () => {
const [name, setName] = React.useState('');
const [password, setPassword] = React.useState('');
const onNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
const onPasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
};
return (
<form>
<input
type="text"
value={name}
onChange={onNameChange}
placeholder="Name"
/>
<input
type="password"
value={password}
onChange={onPasswordChange}
placeholder="Password"
/>
<button type="submit">Submit</button>
</form>
);
};
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7169142/Screenshot_2020-03-13_at_22.40.56.png)
Elm
- Purely functional language.
- Elm provides the ability to interoperate with JavaScript through ports and web components.
- A built-in architecture for organizing code makes managing data flow a breeze.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
import Browser
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
main =
Browser.sandbox { init = init, update = update, view = view }
-- MODEL
type alias Model =
{ name : String
, password : String
}
init : Model
init =
Model "" ""
-- UPDATE
type Msg
= Name String
| Password String
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Password password ->
{ model | password = password }
-- VIEW
view : Model -> Html Msg
view model =
Html.form []
[ viewInput "text" "Name" model.name Name
, viewInput "password" "Password" model.password Password
, button [] [ text "Submit" ]
]
viewInput : String -> String -> String -> (String -> msg) -> Html msg
viewInput t p v toMsg =
input [ type_ t, placeholder p, value v, onInput toMsg ] []
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7169142/Screenshot_2020-03-13_at_22.40.56.png)
Comparison
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7138027/excalidraw-202034204434.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Important points:
-
Interoperability with JavaScript
-
Learning curve
-
Low migration cost and easy setup
-
IDE support, ecosystem
Setup cost
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Setup cost
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
ReasonML
3 steps:
npm install --save-dev bs-platform reason-react
{
"name": "your-project-name",
"reason": {
"react-jsx": 3
},
"sources": [
{
"dir": "src",
"subdirs": true
}
],
"suffix": ".bs.js",
"bs-dependencies": [
"reason-react"
],
"refmt": 3
}
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7132808/Screenshot_2020-03-03_at_19.39.21.png)
Setup cost
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
PureScript
3 steps:
yarn global add purescript spago
yarn add -D purs-loader
spago init
spago install purescript-react-basic
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7133216/Screenshot_2020-03-03_at_21.34.12.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7133220/Screenshot_2020-03-03_at_21.34.48.png)
Setup cost
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
TypeScript
6 steps:
yarn add -D typescript @babel/preset-typescript fork-ts-checker-webpack-plugin
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7135835/Screenshot_2020-03-04_at_13.15.24.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7135839/Screenshot_2020-03-04_at_13.17.09.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7135848/Screenshot_2020-03-04_at_13.17.50.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7135856/Screenshot_2020-03-04_at_13.19.02.png)
{
"compilerOptions": {
"lib": ["es6", "dom", "es2017"],
"checkJs": true,
"allowJs": true,
"jsx": "react",
"allowSyntheticDefaultImports": true,
"strict": true,
"esModuleInterop": true,
"noEmitOnError": false
},
"exclude": ["node_modules"],
"include": ["src/**/*"]
}
Setup cost
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Elm
3 steps:
yarn add -D react-elm-components elm-webpack-loader
{
"version": "0.0.1",
"type": "application",
"summary": "Elm <> Console",
"license": "Apache",
"source-directories": ["src/elm"],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/browser": "1.0.0",
"elm/core": "1.0.0",
"elm/html": "1.0.0",
"elm/json": "1.0.0"
},
"indirect": {
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.0"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7137305/Screenshot_2020-03-04_at_17.45.05.png)
Elm installed globally
Setup cost
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Summary
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
module KnowMoreLink = {
[@bs.module "./KnowMoreLink.js"]
[@react.component]
external make: (
~href: string
~text: string = ?
) => React.element = "default";
};
ReasonML
JavaScript in ReasonML
BuckleScript bindings
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7171142/Screenshot_2020-03-15_at_13.47.23.png)
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
ReasonML
ReasonML in JavaScript
import { make as getUser } from './User/index.bs';
const user = getUser();
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
PureScript
JavaScript in PureScript
exports.unsafeHead = function(arr) {
if (arr.length) {
return arr[0];
} else {
throw new Error('empty array');
}
};
foreign import unsafeHead :: forall a. Array a -> a
Foreign import declaration
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7171151/Screenshot_2020-03-15_at_13.50.12.png)
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
PureScript
PureScript in JavaScript
import { button as Button } from './Button/Button.purs';
<Button>Submit</Button>
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
TypeScript
JavaScript in TypeScript
// Dropdown.d.ts
type Props = {
options: Array<{ content: string }>;
dismiss(): void;
position: 'bottom' | 'right';
};
declare const Dropdown: React.FC<Props>;
export default Dropdown;
-
allowJs: true
- Declaration file for JS code
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7171152/Screenshot_2020-03-15_at_13.52.27.png)
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
TypeScript
TypeScript in JavaScript
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7186063/Screenshot_2020-03-20_at_13.27.40.png)
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Elm
"JavaScript in Elm"
var app = Elm.Main.init({
node: document.getElementById('elm'),
flags: locale
});
1. Flags
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Elm
"JavaScript in Elm"
2. Ports
var app = Elm.Main.init({
node: document.getElementById('elm')
});
app.ports.cache.subscribe(function(data) {
localStorage.setItem('cache', JSON.stringify(data));
});
app.ports.activeUsers.send(activeUsers);
JS interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Elm
Elm in JavaScript
import Button from './elm/Button.elm';
import Elm from 'react-elm-components';
<Elm src={Button.Elm.Main} />
Migration cost
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7171724/Screenshot_2020-03-15_at_19.33.18.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Migration cost
Mental model
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7255386/Screenshot_2020-04-13_at_18.48.05.png)
Type soundness
- TypeScript is unsound by design
- Elm, PureScript and ReasonML guarantee more soundness
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Type soundness
But... dynamic/static typing interop is unsound in all of these languages
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7288326/Screenshot_2020-04-23_at_14.11.25.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Type soundness
Ensuring soundness in dynamic/static typing interop comes with a runtime cost
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7288340/Screenshot_2020-04-23_at_14.16.07.png)
Ecosystem
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Ecosystem
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
IDE support
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7265480/Screenshot_2020-04-16_at_14.39.54.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7265481/Screenshot_2020-04-16_at_14.40.18.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7265485/Screenshot_2020-04-16_at_14.40.39.png)
- VS Code written in
TypeScript
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Popularity on GitHub
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7171728/Screenshot_2020-03-15_at_19.41.27.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7171748/Screenshot_2020-03-15_at_19.51.25.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7171774/Screenshot_2020-03-15_at_20.06.27.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7177775/Screenshot_2020-03-17_at_22.10.50.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7287912/Screenshot_2020-04-23_at_12.21.56.png)
Real world comparison
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7287921/Screenshot_2020-04-23_at_12.24.27.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7287915/Screenshot_2020-04-23_at_12.22.59.png)
Real world comparison
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Real world comparison
- It is biased
- These are different implementations
- There's a big margin for error
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Bundle size in KB
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7287980/Screenshot_2020-04-23_at_12.46.40.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Bundling time in ms
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7287991/Screenshot_2020-04-23_at_12.50.18.png)
What did we choose and what's the plan?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335683/Elm_logo.svg.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335687/1_0ei2MOQxAzF7krm-v60wnQ.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335691/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335696/PureScript_Logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335683/Elm_logo.svg.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335687/1_0ei2MOQxAzF7krm-v60wnQ.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335691/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335696/PureScript_Logo.png)
We needed good JavaScript interop
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335683/Elm_logo.svg.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335687/1_0ei2MOQxAzF7krm-v60wnQ.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335691/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335696/PureScript_Logo.png)
We needed straightforward setup and good IDE support
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335683/Elm_logo.svg.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335687/1_0ei2MOQxAzF7krm-v60wnQ.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335691/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7335696/PureScript_Logo.png)
We needed a low migration cost
![https://twitter.com/markdalgleish/status/1217035225550602246/](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7138103/EOPHFGRU4AEvyfK.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
We chose TypeScript
Hasura Console is a big, opensource project
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Hasura Console is a big, opensource project
Low migration cost allows to keep velocity high.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Hasura Console is a big, opensource project
Low setup cost allows to keep velocity high.
Smallest difference between languages won't scare contributors.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
Gradually typed language fits our needs
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7288238/Screenshot_2020-04-23_at_13.52.54.png)
Adoption plan
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7187296/Untitled_2.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7472259/Screenshot_2020-06-16_at_23.50.22.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7265470/Screenshot_2020-04-16_at_14.36.07.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7265474/Screenshot_2020-04-16_at_14.36.58.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7265476/Screenshot_2020-04-16_at_14.37.34.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7265477/Screenshot_2020-04-16_at_14.37.50.png)
...but getting closer!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7460425/Screenshot_2020-06-12_at_20.56.23.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7460427/Screenshot_2020-06-12_at_20.56.34.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7460428/Screenshot_2020-06-12_at_20.56.44.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7460431/Screenshot_2020-06-12_at_20.57.23.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7460435/Screenshot_2020-06-12_at_20.58.05.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7460437/Screenshot_2020-06-12_at_20.59.13.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7460439/Screenshot_2020-06-12_at_20.59.39.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7460450/Screenshot_2020-06-12_at_21.03.54.png)
Summary
What will you choose?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
We chose TypeScript.
It's not about the language
It's about the context
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1268749/images/7068349/logo.png)
HolyJS: Static Typing: Which Language to Choose?
By Aleksandra Sikora
HolyJS: Static Typing: Which Language to Choose?
Statically typed language? Sounds cool! Statically typed language and large JavaScript codebase? Sounds like a lot of work… Learn how we evaluated our options in Hasura and made the decision on which language to choose! We wanted to introduce a statically typed frontend language to the Hasura Console for quite some time now. Recently we evaluated some options such as PureScript, TypeScript, ReasonML, and Elm. During this talk, I’m going to show the pros and cons of the languages we analyzed. I’ll present how their adoption would look like and what catches we would face along the way. I will also tell what we finally chose and which aspects affected our decision the most.
- 1,537