migrate-to-shoehorn
Replaces dangerous 'as' type assertions in tests with safer, partial data patterns.
Install
mkdir -p .claude/skills/migrate-to-shoehorn && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/11496" && unzip -o skill.zip -d .claude/skills/migrate-to-shoehorn && rm skill.zipInstalls to .claude/skills/migrate-to-shoehorn
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Migrate test files from `as` type assertions to @total-typescript/shoehorn. Use when user mentions shoehorn, wants to replace `as` in tests, or needs partial test data.Key capabilities
- →Replace `as Type` assertions with `fromPartial()`
- →Replace `as unknown as Type` assertions with `fromAny()`
- →Pass partial data in tests while maintaining type safety
- →Pass intentionally wrong data in tests while maintaining autocomplete
- →Force full object validation with `fromExact()`
- →Install `@total-typescript/shoehorn` for type-safe testing
How it works
This skill migrates test files from `as` type assertions to `@total-typescript/shoehorn` by replacing `as Type` with `fromPartial()` and `as unknown as Type` with `fromAny()`. It uses `fromPartial()` for partial data and `fromAny()` for intentionally wrong data.
Inputs & outputs
When to use migrate-to-shoehorn
- →Refactoring tests
- →Removing type assertions
- →Handling partial test objects
- →Improving test safety
About this skill
Migrate to Shoehorn
Why shoehorn?
shoehorn lets you pass partial data in tests while keeping TypeScript happy. It replaces as assertions with type-safe alternatives.
Test code only. Never use shoehorn in production code.
Problems with as in tests:
- Trained not to use it
- Must manually specify target type
- Double-as (
as unknown as Type) for intentionally wrong data
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 purpose
After:
import { fromAny } from "@total-typescript/shoehorn";
getUser(fromAny({ body: { id: 123 } }));
When to use each
| Function | Use case |
|---|---|
fromPartial() | Pass partial data that still type-checks |
fromAny() | Pass intentionally wrong data (keeps autocomplete) |
fromExact() | Force full object (swap with fromPartial later) |
Workflow
-
Gather requirements - ask user:
- What test files have
asassertions causing problems? - Are they dealing with large objects where only some properties matter?
- Do they need to pass intentionally wrong data for error testing?
- What test files have
-
Install and migrate:
- Install:
npm i @total-typescript/shoehorn - Find test files with
asassertions:grep -r " as [A-Z]" --include="*.test.ts" --include="*.spec.ts" - Replace
as TypewithfromPartial() - Replace
as unknown as TypewithfromAny() - Add imports from
@total-typescript/shoehorn - Run type check to verify
- Install:
When not to use it
- →When the code is for production environments
- →When the user does not want to replace `as` assertions in tests
- →When the user does not need to handle partial test data
Limitations
- →Shoehorn should only be used in test code, not production code.
- →`fromPartial()` is used to pass partial data that still type-checks.
- →`fromAny()` is used to pass intentionally wrong data while keeping autocomplete.
How it compares
This migration replaces unsafe `as` assertions with type-safe alternatives, improving test reliability compared to manual type casting.
Compared to similar skills
migrate-to-shoehorn side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| migrate-to-shoehorn (this skill) | 0 | 3mo | Review | Intermediate |
| tdd-workflow | 6 | 4mo | Review | Intermediate |
| migrate | 1 | 5mo | Review | Intermediate |
| agent-implementer-sparc-coder | 1 | 6mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
tdd-workflow
affaan-m
在编写新功能、修复错误或重构代码时使用此技能。强制执行测试驱动开发,包含单元测试、集成测试和端到端测试,覆盖率超过80%。
migrate
alirezarezvani
Migrate from Cypress or Selenium to Playwright. Use when user mentions "cypress", "selenium", "migrate tests", "convert tests", "switch to playwright", "move from cypress", or "replace selenium".
agent-implementer-sparc-coder
ruvnet
Agent skill for implementer-sparc-coder - invoke with $agent-implementer-sparc-coder
tdd-migrate
parcadei
TDD workflow for migrations - orchestrate agents, zero main context growth
react18-enzyme-to-rtl
ArryoRuma
Provides exact Enzyme → React Testing Library migration patterns for React 18 upgrades. Use this skill whenever Enzyme tests need to be rewritten - shallow, mount, wrapper.find(), wrapper.simulate(), wrapper.prop(), wrapper.state(), wrapper.instance(), Enzyme configure/Adapter calls, or any test fil
hexagonal-architecture
jssmy
Design, implement, and refactor Ports & Adapters systems with clear domain boundaries, dependency inversion, and testable use-case orchestration across TypeScript, Java, Kotlin, and Go services. Use for: new features needing long-term maintainability, decoupling domain logic from frameworks/DB/HTTP,