fp-ts
fp-ts copied to clipboard
What's the difference between Map and Record?
📖 Documentation
As the title asks, what's the difference between Map and Record?
I noticed that Record at https://gcanti.github.io/fp-ts/modules/Record.ts.html had more functions under "utils" than does Map at https://gcanti.github.io/fp-ts/modules/Map.ts.html, but that's about it.
How do I know when I want to use Map or Record?
Record
is the module about what in TypeScript is named Record
and it's a plain object.
Map
is the module about this Map
.
How do I know when I want to use Map or Record?
This has very little to do with TypeScript or fp-ts
, it has to do with what problem you have to solve, so I don't thin this is the right place do discuss it. Anyway, both can be used as key-value stores. With Map
you can use any object as key (lookups have to use the same reference though) and the insertion order is maintained. On the other hand, plain object are faster (if performance is a concern for your use case).
Just to add to what @DenisFrezzato wrote, I don't believe the operations for Map are immutable either. So, if you wanted to use them in pure manner then you'd have to write wrappers around them to always return a new Map.
@TheWix actually they are all immutable cause Map
is just a signature extension over ReadonlyMap
.
There are actually no mutable operations in fp-ts
. If you need one you should use IORef
and implement the mutable operations by yourself.
@mlegenhausen Oops, sorry. I was referring to The built in JS Map rather than the fp-ts one.
Does the Map
in the docs refer to the js or fp-ts Map?
@TheWix Actually fp-ts
Map
module is built on top of native Map
What are the differences in use-cases between
- the js
Record
, - the fp-ts
Record
(assuming this exists), - the js
Map
, and - the fp-ts
Map
Thanks for your time, sorry if these are simple questions, I'm a little lost.
What are the differences in use-cases between
- the js Record
- the fp-ts Record (assuming this exists),
- the js Map, and
- the fp-ts Map
First of all, there is no Record
in js, so not sure what you mean there. Are you referring to the Record
type in Typescript?
There is no difference between Record
in TS and Record
in fp-ts except that fp-ts provides some nicer utilities for working and interacting with Record
s. For example, accessing a property directly versus using lookup
from fp-ts will give you different behaviour:
import * as R from 'fp-ts/Record'
declare const myRecord: Record<string, string>
// x will be typed as a string, even though myRecord may not have the 'someKey' property
const x = myRecord.someKey
// x will be typed as Option<string>, correctly reflecting the fact that myRecord may not have the
// 'someKey' property
const y = R.lookup("someKey", myRecord)
In terms of when to use a Map
vs a Record
, there's no right answer it depends on what you are trying to do in your program as one data structure might be more optimal than another (as @DenisFrezzato already mentioned). For example, a Map can have keys of any type including objects or functions. There are many articles online talking about when you might wish to use a Map
such as https://dmitripavlutin.com/maps-vs-plain-objects-javascript/
Once again, fp-ts
Map gives you nice utilities for interacting with a map which are safer than what the native Map functions will give you in Typescript. So if you are looking for better type-safety in your codebase then you can always look into using fp-ts
to interact with your Maps rather than using the native JS methods
Hope that helps! :)
Would be interesting to have real world examples where a Map
is more superior than a Record
in a functional programming context. In my 10 years programming exclusively JS I never had the need for a Map
.
The advantage of using complex objects as keys comes at the cost that each lookup seems to be O(n)
(in fp-ts
) where as it is O(log n)
or even O(1)
for a Record
.
We normally solve the problem with complex keys by defining a io-ts
type that converts the object to a string representation that can then be used as lookup key.