I'll leave the alternatives of the code to the other answers, but just to make a comment about functional programming:
Functional programming has three core tenets as I see it:
- Functions are first class citizens (you can pass them as arguments, put them in lists)
- Functions are deterministic - (for a function call of the same arguments, it always returns the same thing).
- Functions don't cause side effects.
Now with the second two points it's apparent that in a purely functional context, some things simply are not possible:
- A function that generates a random number
- A function that gets the current time
- A function that fetches some data from a database or API
- A function that writes data to a file.
So the point here is - even if you're adopting a functional paradigm, at some point, unless your program is just a simple 'sort this list' type program, it likely needs to have side effects and encounter nondeterministic behavior.
In your case, reading from a file is nondeterministic behavior.
So the question is, in a functional paradigm, how do you deal with this?
Some resources I recommend looking at:
https://stackoverflow.com/questions/330371/are-databases-and-functional-programming-at-odds
Basically the suggestion I make is that you isolate your nondeterministic code into functions that just do that non-deterministic behavior. You then pass those functions into the logic functions don't need to know if the function is deterministic or not.
From your example, lets say you have this:
function getFileTexts(filePaths) {
const fileTexts = filePaths.map((filePath: string) => {
return fs.readFileSync(filePath, 'utf-8')
})
return fileTexts;
}
So the problem with this is that the fs.readFileSync
is nondeterministic.
What you can do pass the 'read file' function in, as an argument.
function getFileTexts(filePaths, readFileFn) {
const fileTexts = filePaths.map((filePath: string) => {
return readFileFn(filePath);
})
return fileTexts;
}
And you would call this with:
const fileTexts = getFileTexts(filePaths, (filePath) => fs.readFileSync(filePath, 'utf-8'));
Now, even though in the real world that function isn't going to deterministic, at least now it's possible for it to be.
That is, in your tests for example, you pass an alternative, purely deterministic function like:
const fileTexts = getFileTexts(filePaths, () => 'foo bar biz');