/migrate-to-shoehorn
将测试文件从 `as` 类型断言迁移到 @total-typescript/shoehorn。适用于用户提到 shoehorn、想替换测试中的 `as`,或需要局部测试数据时。
$ npx -y skills add vinvcn/mattpocock-skills-zh-cn --skill migrate-to-shoehorn --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/migrate-to-shoehorn
Context preview
The summary Claude sees to decide when to auto-load this skill.
将测试文件从 `as` 类型断言迁移到 @total-typescript/shoehorn。适用于用户提到 shoehorn、想替换测试中的 `as`,或需要局部测试数据时。
SKILL.md
migrate-to-shoehorn.SKILL.mdname: migrate-to-shoehorn
description: 将测试文件从 `as` 类型断言迁移到 @total-typescript/shoehorn。适用于用户提到 shoehorn、想替换测试中的 `as`,或需要局部测试数据时。
Migrate to Shoehorn
Why shoehorn?
`shoehorn` 允许你在 tests 中传入 partial data,同时保持 TypeScript 满意。它用 type-safe alternatives 替换 `as` assertions。
**只用于 test code。** 永远不要在 production code 中使用 shoehorn。
Tests 中 `as` 的问题:
- 经过训练,不去使用它
- 必须手动指定 target type
- 对故意错误的数据需要 double-as(`as unknown as Type`)
Install
npm i @total-typescript/shoehorn
Migration patterns
Large objects with few needed properties
Before:
type Request = {
body: { id: string };
headers: Record<string, string>;
cookies: Record<string, string>;
// ...20 more properties
};
it("gets user by id", () => {
// Only care about body.id but must fake entire Request
getUser({
body: { id: "123" },
headers: {},
cookies: {},
// ...fake all 20 properties
});
});After:
import { fromPartial } from "@total-typescript/shoehorn";
it("gets user by id", () => {
getUser(
fromPartial({
body: { id: "123" },
}),
);
});`as Type` → `fromPartial()`
Before:
getUser({ body: { id: "123" } } as Request);After:
import { fromPartial } from "@total-typescript/shoehorn";
getUser(fromPartial({ body: { id: "123" } }));`as unknown as Type` → `fromAny()`
Before:
getUser({ body: { id: 123 } } as unknown as Request); // wrong type on purposeAfter:
import { fromAny } from "@total-typescript/shoehorn";
getUser(fromAny({ body: { id: 123 } }));When to use each
| Function | Use case | | --------------- | -------------------------------------------------- | | `fromPartial()` | 传入仍能 type-check 的 partial data | | `fromAny()` | 传入故意错误的数据(保留 autocomplete) | | `fromExact()` | 强制 full object(之后可换成 fromPartial) |
Workflow
1. **Gather requirements** — 询问用户:
- 哪些 test files 中的 `as` assertions 造成问题?
- 是否在处理大型 objects,但只关心部分 properties?
- 是否需要传入故意错误的数据来测试 error paths?
2. **Install and migrate**:
- [ ] Install: `npm i @total-typescript/shoehorn`
- [ ] 查找 test files 中的 `as` assertions: `grep -r " as [A-Z]" --include="*.test.ts" --include="*.spec.ts"`
- [ ] 用 `fromPartial()` 替换 `as Type`
- [ ] 用 `fromAny()` 替换 `as unknown as Type`
- [ ] 添加来自 `@total-typescript/shoehorn` 的 imports
- [ ] 运行 type check 验证
Read more
name: migrate-to-shoehorn description: 将测试文件从 `as` 类型断言迁移到 @total-typescript/shoehorn。适用于用户提到 shoehorn、想替换测试中的 `as`,或需要局部测试数据时。
Migrate to Shoehorn
Why shoehorn?
`shoehorn` 允许你在 tests 中传入 partial data,同时保持 TypeScript 满意。它用 type-safe alternatives 替换 `as` assertions。
**只用于 test code。** 永远不要在 production code 中使用 shoehorn。
Tests 中 `as` 的问题:
- 经过训练,不去使用它
- 必须手动指定 target type
- 对故意错误的数据需要 double-as(`as unknown as Type`)
Install
npm i @total-typescript/shoehorn
Migration patterns
Large objects with few needed properties
Before:
type Request = {
body: { id: string };
headers: Record<string, string>;
cookies: Record<string, string>;
// ...20 more properties
};
it("gets user by id", () => {
// Only care about body.id but must fake entire Request
getUser({
body: { id: "123" },
headers: {},
cookies: {},
// ...fake all 20 properties
});
});After:
import { fromPartial } from "@total-typescript/shoehorn";
it("gets user by id", () => {
getUser(
fromPartial({
body: { id: "123" },
}),
);
});`as Type` → `fromPartial()`
Before:
getUser({ body: { id: "123" } } as Request);After:
import { fromPartial } from "@total-typescript/shoehorn";
getUser(fromPartial({ body: { id: "123" } }));`as unknown as Type` → `fromAny()`
Before:
getUser({ body: { id: 123 } } as unknown as Request); // wrong type on purposeAfter:
import { fromAny } from "@total-typescript/shoehorn";
getUser(fromAny({ body: { id: 123 } }));When to use each
| Function | Use case | | --------------- | -------------------------------------------------- | | `fromPartial()` | 传入仍能 type-check 的 partial data | | `fromAny()` | 传入故意错误的数据(保留 autocomplete) | | `fromExact()` | 强制 full object(之后可换成 fromPartial) |
Workflow
1. **Gather requirements** — 询问用户:
- 哪些 test files 中的 `as` assertions 造成问题?
- 是否在处理大型 objects,但只关心部分 properties?
- 是否需要传入故意错误的数据来测试 error paths?
2. **Install and migrate**:
- [ ] Install: `npm i @total-typescript/shoehorn`
- [ ] 查找 test files 中的 `as` assertions: `grep -r " as [A-Z]" --include="*.test.ts" --include="*.spec.ts"`
- [ ] 用 `fromPartial()` 替换 `as Type`
- [ ] 用 `fromAny()` 替换 `as unknown as Type`
- [ ] 添加来自 `@total-typescript/shoehorn` 的 imports
- [ ] 运行 type check 验证
Repo: vinvcn/mattpocock-skills-zh-cn
Other skills on mattpocock-skills.
- /ask-matt
询问当前情境适合哪个技能或流程;它是本仓库所有 skills 的路由器。
Open skill - /code-review
从固定点(commit、branch、tag 或 merge-base)开始,按 Standards(代码是否符合本仓库记录的编码标准?)和 Spec(代码是否符合来源 issue/PRD 的要求?)两个轴线审查变更。两个审查会在并行子代理中运行,并并排报告。适用于用户想审查 branch、PR、进行中的变更,或要求 “review since X” 时。
Open skill - /codebase-design
用于设计深模块的共享词汇。适用于用户想设计或改进模块接口、寻找深化机会、决定 seam 放在哪里、让代码更容易测试或更适合 AI 导航,或其他技能需要深模块词汇时。
Open skill - /diagnosing-bugs
面向棘手缺陷和性能回退的诊断循环。适用于用户说 “diagnose” / “debug this”,或报告某些东西 broken、throwing、failing、slow 时。
Open skill - /domain-modeling
构建并打磨项目的领域模型。适用于用户想明确领域术语或通用语言、记录架构决策,或其他技能需要维护领域模型时。
Open skill - /grill-with-docs
一个用来打磨计划或设计的持续追问式访谈,并在过程中创建文档(ADRs 和词汇表)。
Open skill

