Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Fp Ts Refactor

ASecurity

当把命令式 TypeScript 代码(try/catch、null 检查、回调、类 DI、循环、Promise 链)迁移到 fp-ts 函数式范式时使用;产出 Either/Option/Task/Reader 等价改写、组合管线与渐进迁移路径;不适用于简单同步代码、性能热点循环、第三方接口边界与团队不熟悉 fp-ts 的场景。触发词:fp-ts、TaskEither、Either/Option、函数式重构

3 stars
0 votes
0 copies
2 views
Added 9/19/2026
ai-agentsjavascripttypescriptjavabashexpressapibackend

Works with

cursorcliapi

Security Analysis

A100/100

Scanned 9/19/2026

$npx -y skills add findscripter/everything-skills --skill fp-ts-refactor --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Fp Ts Refactor?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Fp Ts Refactor
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/findscripter-fp-ts-refactor/badge)](https://www.skillsdirectory.com/skills/findscripter-fp-ts-refactor)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: fp-ts-refactor
title: 命令式 TS 重构为 fp-ts
description: 当把命令式 TypeScript 代码(try/catch、null 检查、回调、类 DI、循环、Promise 链)迁移到 fp-ts 函数式范式时使用;产出 Either/Option/Task/Reader 等价改写、组合管线与渐进迁移路径;不适用于简单同步代码、性能热点循环、第三方接口边界与团队不熟悉 fp-ts 的场景。触发词:fp-ts、TaskEither、Either/Option、函数式重构
domain: 研发/backend
triggers: [fp-ts 重构, 命令式转函数式, try/catch 转 Either, null 转 Option, 回调转 Task, 类 DI 转 Reader, Promise 链转 TaskEither, pipe flatMap 组合, TaskEither 迁移]
tags: [fp-ts, typescript, 重构, 函数式编程, either, option, taskeither, reader, 迁移]
level: 进阶
status: stable
agents: [claude-code, codex, cursor, gemini-cli]
tools: [Read, Edit, Grep, Glob, Bash]
requires: []
related: [fp-ts-pragmatic-guide, typescript-advanced-types, javascript-modern-pro, error-handling-patterns]
combines_with: [typescript-advanced-types, error-handling-patterns]
license: MIT
source: sickn33/agentic-awesome-skills
source_license: MIT
---
## 何时使用

- 正在把现有命令式 TypeScript 代码库逐步迁移到 fp-ts 函数式范式。
- 任务核心是把 `try/catch`、null 检查、回调、类式依赖注入(DI)、命令式循环、`Promise` 链转换成函数式等价物。
- 你需要的是迁移策略与权衡取舍,而非孤立的 fp-ts 用法示例。

不该用(保持命令式更好):

- 简单同步纯函数(如 `formatName`),套 `pipe` 只增加复杂度无收益。
- 性能热点循环:fp-ts 的 `A.map`/`A.filter` 会产生中间数组,处理百万级元素时保留 `for` 循环。
- 第三方库接口边界(Express 中间件等):只在边界处转换,内部保持库要求的形态。
- 团队不熟悉 fp-ts、或一次性 null 检查(`user?.name ?? 'x'` 已够),或错误类型无所谓(反正要 throw/log)的场景。
- 测试代码:以可读为先,不必函数式。

## 步骤 / 指令

通用迁移流程(以 try/catch → Either 为例,其它范式同构):

1. 确定错误类型:列出可能发生的错误,定义错误类型(推荐带 `_tag` 的联合类型)。
2. 改返回类型:把 `T` 改为 `Either<E, T>`(异步用 `TaskEither<E, T>`)。
3. 替换 `throw new Error(...)` 为 `E.left(...)`;替换 `return value` 为 `E.right(value)`。
4. 删除 `try/catch` 块。
5. 用 `pipe` + `E.flatMap`(异步 `TE.flatMap`)串联各步,错误自动短路传播。
6. 在系统边界用 `E.match`/`O.match`/`getOrElse`/`toNullable` 与非 fp 代码对接。

null → Option:用 `O.fromNullable` 在边界包裹;返回类型 `T | null` 改 `Option<T>`;用 `O.map`/`O.flatMap`/`O.filter` 取代 if 判空。需要错误信息时 `E.fromOption(() => err)` 升级为 Either。

回调 → Task:优先改用 `fs/promises` 等 Promise API,再用 `TE.tryCatch` 包裹;多任务用 `A.traverse(TE.ApplicativePar)`(并行,遇错即停)或 `TE.ApplicativeSeq`(顺序)。

类 DI → Reader:把依赖收敛为 `AppEnv` 接口,服务函数返回 `ReaderTaskEither<AppEnv, E, A>`,用 `RTE.ask` 取环境、`RTE.flatMapTaskEither` 调依赖;运行时注入真实/测试 env:`updateEmail(id, email)(env)()`。

循环 → 函数式:`for` → `A.map`/`A.filter`/`A.reduce`,单遍聚合可用 `A.foldMap(monoid)`;嵌套循环 → `A.flatMap` + `A.uniq(Eq)`;`while` → 递归辅助函数或 `RA.unfold`。

Promise 链 → TaskEither:`.then` → `TE.map`/`TE.flatMap`,`.catch` → `TE.orElse`/`TE.mapLeft`,条件抛错 → `TE.filterOrElse`,`Promise.all` → `A.traverse(TE.ApplicativePar)`。

渐进采用策略:① 从边界(API/DB/文件/输入校验)起步;② 建桥接函数双向转换;③ 按模块迁移、先内部后公开 API;④ 类型驱动(先改签名让编译器标出所有调用点);⑤ 用测试当文档。

## 示例

同步 try/catch → Either(错误进类型,组合自动短路):

```typescript
import * as E from 'fp-ts/Either';
import * as J from 'fp-ts/Json';
import { pipe } from 'fp-ts/function';

const parseJSON = (input: string): E.Either<Error, unknown> =>
  pipe(J.parse(input), E.mapLeft((e) => new Error(`Invalid JSON: ${e}`)));

const validateUser = (data: unknown): E.Either<Error, User> => {
  if (!data || typeof data !== 'object') return E.left(new Error('Data must be an object'));
  const obj = data as Record<string, unknown>;
  if (typeof obj.name !== 'string') return E.left(new Error('Name is required'));
  if (typeof obj.age !== 'number') return E.left(new Error('Age must be a number'));
  return E.right({ name: obj.name, age: obj.age });
};

const processUserInput = (input: string): E.Either<Error, User> =>
  pipe(parseJSON(input), E.flatMap(validateUser));
```

异步编排用 `TE.Do`/`TE.bind` 累积上下文,执行时注意双重调用 `await getUserWithPosts('123')()`:

```typescript
const getUserWithPosts = (id: string): TE.TaskEither<Error, { user: User; posts: Post[] }> =>
  pipe(TE.Do, TE.bind('user', () => fetchUser(id)), TE.bind('posts', () => fetchUserPosts(id)));
```

可复用桥接(命令式 ↔ fp-ts 之间过渡):

```typescript
const tryCatchSync = <A>(f: () => A): E.Either<Error, A> =>
  E.tryCatch(f, (e) => (e instanceof Error ? e : new Error(String(e))));
const fromPromise = <A>(p: Promise<A>): TE.TaskEither<Error, A> =>
  TE.tryCatch(() => p, (e) => (e instanceof Error ? e : new Error(String(e))));
```

命令式 → fp-ts 速查表(节选):

| 命令式 | fp-ts 等价 |
|---|---|
| `try/catch` | `E.tryCatch()` / `TE.tryCatch()` |
| `throw` / `return` | `E.left()` / `E.right()`(TE 同理) |
| `if (x === null)` / `x ?? d` | `O.fromNullable()` / `O.getOrElse()` |
| `x?.prop` | `O.map()` / `O.flatMap()` |
| `array.map/filter/reduce/find` | `A.map/filter/reduce(foldMap)/findFirst` |
| `Promise.then/catch` | `TE.map`+`flatMap` / `TE.orElse`+`mapLeft` |
| `Promise.all` | `A.traverse(TE.ApplicativePar)` |
| `new Class(deps)` | `R.asks()` / `RTE.ask()` |
| `for...of` / `while` | `A.map`+`reduce` / 递归、`unfold()` |

## 注意事项

常见坑(源中 Pitfalls,务必规避):

- 忘记运行 Task:`fetchData()` 仍是 Task,结果需 `await fetchData()()` 双重调用。
- 不要中途逃出 fp-ts 生态:拿到 `Either` 就 `E.isLeft` 判断后 `throw`,应改用 `TE.fromEither` 留在管线内。
- 该用 `flatMap` 却用 `map`:返回 monad 的函数用 `map` 会得到嵌套 `Either<E, Either<E, A>>`,用 `flatMap` 摊平。
- 丢失错误上下文:`TE.tryCatch` 第二参要保留 `reason`(`(reason) => new Error(...${reason})`),更佳用带 `_tag` 的类型化错误。
- 滥用 `fromNullable`:简单取值 `user?.name ?? 'x'` 即可,仅在多步链式时才用 Option。
- 务必处理 Left/None:禁止 `(result as E.Right<User>).right` 之类不安全断言,用 `E.getOrElse`/`E.match`。

迁移是过程而非目的:从小处改起、保持务实(并非一切都要函数式)、类型驱动、充分测试、沉淀团队模式、复核收益。目标是更可维护、类型安全的代码,而非为函数式而函数式。

## 互见

- 研发/misc 下其它 TypeScript / 函数式相关条目。
- fp-ts 官方模块文档:`Either` / `Option` / `Task` / `TaskEither` / `Reader` / `ReaderTaskEither` / `Array` / `Monoid`。

---

采编自 sickn33/antigravity-awesome-skills(MIT)。

Attribution

findscripterfindscripter
View sourceSee grades on GitHubMore from findscripter →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698621 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →