Hey! I want to suggest freezing empty to avoid occasional mutation (e.g. by third-parties).
import { empty } from 'fp-ts/lib/Array';
function foo(arr: Array<number>) {
arr.push(1); // might be not that obvious
}
foo(empty); // Neither compile-time nor runtime error
// All the code that depends on `empty` is broken after that
import { empty } from 'fp-ts/lib/Array';
function foo(arr: Array<number>) {
arr.push(1);
}
foo(empty); // No compile-time error, but runtime exception
const empty: Array<never> = Object.freeze([]);
My team several times faced subtle bugs caused by empty been mutated occasionally by third-party code. I think that confidence that empty won't be mutated worth possible runtime exception at development time.
1) Adding readonly to empty's type - inconveniently restrict possible usages of empty cause you can't pass readonly Array<T> where you expect Array<T>
2) Object.seal - less strict than Object.freeze, but basically is the same for our case
3) Doing Object.freeze(empty) in every project - easy to forget about
| Software | Version(s) |
| ---------- | ---------- |
| fp-ts | v2.1.0 |
| TypeScript | v3.6.3 |
2 cents here - if we disable mutations on Array then return type of empty should be ReadonlyArray. Otherwise it's a broken contract.
Most helpful comment
2 cents here - if we disable mutations on
Arraythen return type ofemptyshould beReadonlyArray. Otherwise it's a broken contract.