Since first learning of Elm, I’ve only heard good things. I’m convinced Elm could become the future of front-end development in the coming years. Here are some blog posts in the Elm community that have particularly stuck out to me:
- Why Elm is Going to Change the World
- Why I think Elm is the Future of Front End Development
- Why Elm is a future of Frontend? Interview with Preethi Kasireddy
- What Elm and Rust Teach us About the Future
For the moment, I'm not involved in any Elm project. However, I’ve been messing around with Elm a bit. I want to work with Elm more, and I know Elm can bring some incredible things to front-end development.
How can I bring these things to JavaScript, since I am just working with JavaScript presently?
Let's see first what Elm can do for us, as developers.
Why Should I care about Elm ?
This is a common question people ask themselves, and there is a book called Why Elm from O’Reilly.
In this book, they say:
Many of the common issues that front-end developers have to deal with just
don't exist in Elm.
YES! You read it well. They simply don't exist. Imagine yourself not dealing
with undefined is not a function
or odd things like: NaN === NaN
. Some of these weird things have an explanation, but they are still weird.
Elm compiler
Elm has an awesome compiler. Imagine you have a compiler as an assistant.
"Elm ensures that errors will happen at compile time, in front of a developer,
instead of runtime, in front of a user. " - Why Elm
The Elm compiler is awesome Let’s look at one example:
In this example, we were trying to return a String and a number in our if/else. The compiler makes your life easier, explaining to you exactly what the error was and what you can do.
Now, imagine you made a typo. Rather than typing map
you typed nap
.
The compiler explains to you what you did and gives you a few options.
Total immutability
Imagine you don't need to worry about mutable state in your application. Everything is immutable.
Purely Functional
Elm is a purely functional language. This means you can use all the power of Functional Programming in your code.
Here are some good articles talking about
FP.
Reactive Programming
In imperative programming languages, we have:
let a = b + c
If we change the value of b
, a
will not be updated. Elm helps us to have that by computing values from the state.
Strong Static Types
The use of types is one of the main points of using Elm. With strong static types, Elm can infer the types of each variable or function. It prevents a series of mistakes you can make.lso, we don't need to worry about null
or undefined
. Elm has a solution for this.
Bringing these things to JS
We saw what Elm is best used for. Let's see how we can bring these things to JavaScript, if it's possible.
Static Types
There are a few ways you can bring something like static typing to JavaScript.
Flow
We are using Flow in the Formulae project.
Imagine you have a function, and you have used an undeclared variable.
function myFunction() {
let a = b;
}
Flow will explain that you have used an undeclared variable.
➜ formulae_react git:(master) ✗ flow status
src/output_lib/decoders.js:199
199: let a = b;
^ identifier `b`. Could not resolve name
Found 1 error
Now imagine you have a function that receives only a number, what if you pass a string to it?
function timesTwo(x: number) {
return x * 2;
}
function main() {
timesTwo("hello");
}
Flow says the type is incompatible with the expected parameter we created.
➜ formulae_react git:(master) ✗ flow status
src/output_lib/decoders.js:203
203: timesTwo("hello");
^^^^^^^ string. This type is incompatible with the expected
param type of
198: function timesTwo(x: number) {
^^^^^^ number
Found 1 error
These little things can help you a lot in your development phase.
TypeScript
TypeScript has a lot of interesting features. We find people all over the web talking highly about it. Personally, I prefer using Flow, so I'm just mentioning TypeScript here. If you think it's good, go for it!
Redux
For those who work with React, Redux is based on the Elm architecture. So, if you are already using Redux, you are using something Elm-based, and you never thought about it.
We are using Redux and we like it!
If you check a simple structure of a program in Elm, you can see we have a Model,
a function to update and the view. This is very
similar to redux.
import Html exposing (..)
-- MODEL
type alias Model = { ... }
-- UPDATE
type Msg = Reset | ...
update : Msg -> Model -> Model
update msg model =
case msg of
Reset -> ...
...
-- VIEW
view : Model -> Html Msg
view model =
...
Redux First Router
Another thing we think is good is Redux First Router. We are not using it on the project I mentioned earlier, but we liked the idea of having routing state being just another part of the application state.
In our store, we can define all the routes we have:
...
const routesMap = {
HOME: "/", // action <-> url path
PRODUCT: "/product/:id" // :id is a dynamic segment
};
...
These actions will be used in the Reducer, we can change the state once we change the route.
const productsReducer = (state = init(), action = {}) => {
switch (action.type) {
case "HOME":
...
case "PRODUCT":
...
...
Handling routing in elm via navigation is basically the same thing.
Decoders
Elm uses a layer called Decoders, it is a boundary between your front-end and your back-end. We can see this in other languages, but Elm does this very explicitly. In our JavaScript code we created Decoders from the data we received and we created Encoders to the data we send.
As we are using ImmutableJS, we convert the JSON we receive into our own app types. With this, our app now recognizes weird JSON structures easily, and we also add a new validation phase in getting data from our API.
Let's imagine we have an API for Person
. Once we receive the data from our server, we call the decode function and its responsibility is to return a PersonType
.
const Person = {
get: (name: string): Promise<PersonType> => {
return api.get(`${name}`).then(resp => decodePersonType(resp.data));
}
};
In our case, our PersonType
is an immutable Record.
import { Record } from 'immutable'
export default class PersonType extends Record({
name: '',
age: 0,
github: ''
}) {
name: string
age: number
github: string
}
In our code, we have an ApiPerson
type.his maps exactly to the JSON we will receive.
type ApiPerson = {
name: string,
age: number,
github: string
}
decodePersonType(person: ApiPerson) : PersonType{
return new PersonType({
name: person.name,
age: person.age,
github: person.github
})
}
Our decode
function converts the Api type, ApiPerson
to our PersonType
.
Summary
Now you know what are the the good things Elm can bring us. If you can only work in a JavaScript project, you can probably bring some of these Elm feature for your JavaScript code.
Top comments (0)