typescriptfunctional-programmingoption-typefp-ts

What is the advantage of using Option instead of typescript's optional `?` operator?


I am getting started with fp-ts lib and was wondering what is the advantage of using Option type over typescript's default notion of optional values represented by question mark ? operator?


Solution

  • Typescript tells you whether or not you have the value or not with the question mark. However, often you'll want to perform some sort of computation on them and this is when the Option type from fp-ts shines.

    For example, let's say we have two items in a shop and they optionally have prices and we want to write a function to get the price of both of them otherwise we return some value that represents "not for sale". First we'll see how we would do this in vanilla typescript

    type ShopItem = {
        price?:number
    }
    const getPrice = (item1: ShopItem, item2: ShopItem):number | null => {
        const price1 = item1.price;
        const price2 = item2.price;
    
        if (price1 && price2) {
            return price1 + price2;
        }
        return null;
    }
    

    This has a few problems. First, there's a bug in there because if the price was 0, then the item should be for sale but instead our falsey check would short circuit out and return null. Secondly, it doesn't scale very well. If we wanted to add multiple ShopItems or even other types of items with optional values, we'll need to keep checking whether or not those values were null.

    Now let's compare this to the fp-ts example https://codesandbox.io/s/laughing-wu-pffe3

    import { some, none, ap, Option } from "fp-ts/lib/Option";
    import { pipe } from 'fp-ts/lib/pipeable'
    
    type ShopItem = {
        price:Option<number> //this type will either be a Some<number> or None
    }
    const getPrice = (item1: ShopItem, item2: ShopItem): Option<number> =>
      pipe( 
       some((a:number) => (b:number) => a + b), 
       ap(item1.price),
       ap(item2.price)
      );
    

    The way this works is that we get the item1 price and the item2 price and we feed it into the addition function inside the some. Notice how there aren't any null checks as this has been abstracted away into our None type.