Aloha.zone.io

Aloha's technical notes.

View on GitHub

Functional programming in TypeScript

Introduce and demo some useful snippets of FP in TypeScript.

Related libraries:


Keep IMMUTABLE

The best practise in FP is using immutable variables anywhere if possible.

In TypeScript, use const for type declaration and readonly for properties of type/interface and args of functions as much as possible. Avoid using let or var declaration if they are not a must. (Actually, there should always be a way to abandon a mutable variable)

Example:

declare const a : number
const b = a > 0 ? 'positive' : 'negativeOrZero'   // $ExpectedType: 'positive' | 'negativeOrZero'
let b = a > 0 ? 'postive' : 'negativeOrZero'     // $ExpectedType: string

Pure function

Curry

TypeScript is not born to support curry. Node package like [Rambda](https://github.com/ramda/ramda) provides a good implementation of curry, but since we are on Deno with TypeScript, it seems not very direct for us to use it, neither give a cool implementation of it in TS.

A sample for a currying step by step: How to master advanced TypeScript patterns

Also, we can look forward for the proposed feature Variadic Kinds, which will make it easier to define a typed curry function.

Fortunately, Denofun serves a group of useful utilities for FP including curry.

Example:

import curry from "https://deno.land/x/denofun/lib/curry.ts";

const greet = (name: string, age: number) => `hello, I'm ${name} and I'm ${age} years old`;
const curriedGreet = curry(greet);
curriedGreet("Tomasz")(26) 

Practises: using curry

Compose

Moreover, we have a similar pipe function, which also combines the functions. The function parameter is called from right to left in compose, but left to right in pipe.

Practises: using compose

Functor

A Functor is a type that implements map and obeys some laws

Typically, we use pointed function which contains a of function for instantiating a functor.

  Container.of(3)
  // Container(3)

  Container.of(3).map(x => x + 1)
  // Container(4)

Applicative Functor

“Applicative functor” is a kind of “pointed functor” which implements ap function.

Function ap should apply the value of a functor to the value of another functor.

It means: F.of(x).map(f) == F.of(f).ap(F.of(x))

  Container.of(add(2)).ap(Container.of(3))
  // Container(5)

  Container.of(2).map(add).ap(Container.of(3))

Use applicative functor will make a curried function in functor being used like a a normal function call:

  Maybe.of(add).ap(Maybe.of(2)).ap(Maybe.of(3))
  // Maybe(5)

  Task.of(add).ap(Task.of(2)).ap(Task.of(3));
  // Task(5)

Reference

Mostly adequate guide to FP (in javascript)

Mostly adequate guide to FP - 中文

Denofun