原文:https://dev.to/gcanti/interoperability-with-non-functional-code-using-fp-ts-432e
这篇文章的标题是“使用fp-ts与非函数式代码的互操作性”,由Giulio Canti于2019年2月12日发表,并在2021年4月16日更新。文章讨论了如何在不得不与非函数式代码互操作时,使用TypeScript的fp-ts库来处理各种情况。
以下是文章的主要内容翻译:
有时你可能被迫与非函数式编写的代码进行互操作,我们来看看如何处理这种情况。
哨兵值(Sentinels)
用例:一个可能失败并返回陪域中特殊值的API。
示例:Array.prototype.findIndex
解决方案:Option
import { Option, none, some } from 'fp-ts/Option'
function findIndex<A>(as: Array<A>, predicate: (a: A) => boolean): Option<number> {
const index = as.findIndex(predicate)
return index === -1 ? none : some(index)
}
undefined
和 null
用例:一个可能失败并返回 undefined
(或 null
)的API。
示例:Array.prototype.find
解决方案:Option
, fromNullable
import { Option, fromNullable } from 'fp-ts/Option'
function find<A>(as: Array<A>, predicate: (a: A) => boolean): Option<A> {
return fromNullable(as.find(predicate))
}
异常
用例:一个可能抛出异常的API。
示例:JSON.parse
解决方案:Either
, tryCatch
import { Either, tryCatch } from 'fp-ts/Either'
function parse(s: string): Either<Error, unknown> {
return tryCatch(
() => JSON.parse(s),
(reason) => new Error(String(reason))
)
}
随机值
用例:一个返回非确定性值的API。
示例:Math.random
解决方案:IO
import { IO } from 'fp-ts/IO'
const random: IO<number> = () => Math.random()
同步副作用
用例:一个读取和/或写入全局状态的API。
示例:localStorage.getItem
解决方案:IO
import { Option, fromNullable } from 'fp-ts/Option'
import { IO } from 'fp-ts/IO'
function getItem(key: string): IO<Option<string>> {
return () => fromNullable(localStorage.getItem(key))
}
用例:一个读取和/或写入全局状态并且可能抛出异常的API。
示例:readFileSync
解决方案:IOEither
, tryCatch
import * as fs from 'fs'
import { IOEither, tryCatch } from 'fp-ts/IOEither'
function readFileSync(path: string): IOEither<Error, string> {
return tryCatch(
() => fs.readFileSync(path, 'utf8'),
(reason) => new Error(String(reason))
)
}
异步副作用
用例:执行异步计算的API。
示例:从标准输入读取
解决方案:Task
import { createInterface } from 'readline'
import { Task } from 'fp-ts/Task'
const read: Task<string> = () =>
new Promise<string>((resolve) => {
const rl = createInterface({
input: process.stdin,
output: process.stdout
})
rl.question('', (answer) => {
rl.close()
resolve(answer)
})
})
用例:执行可能被拒绝的异步计算的API。
示例:fetch
解决方案:TaskEither
, tryCatch
import { TaskEither, tryCatch } from 'fp-ts/TaskEither'
function get(url: string): TaskEither<Error, string> {
return tryCatch(
() => fetch(url).then((res) => res.text()),
(reason) => new Error(String(reason))
)
}
请注意,代码示例是TypeScript代码,并且需要相应的环境和库来正确执行。