migrate-to-shoehorn
The facts
Its description
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.
The description the agent reads to decide when to use it.
When it starts
The agent picks this skill when the conversation is about cleaning up TypeScript test files, specifically replacing `as` type assertions with the @total-typescript/shoehorn library or passing partial/intentionally wrong test data. It is triggered by the user naming shoehorn, complaining about `as` casts in tests, or needing partial test fixtures.
Things a person might say (the model's guesses)
- “Can you get rid of all the `as` casts in our test files?”
- “I keep having to fake entire objects in my tests — is there something like shoehorn for this?”
- “How do I pass partial test data without TypeScript complaining?”
A model's summary of when it is used.
Licence
MIT, from LICENSE
The terms its author shares it under, which let it be shown here.
Other files in this skill (1) Close
The text
Migrate to Shoehorn
Raw lines 1 to 7Why 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
Migration patterns
Raw lines 26 to 27Large 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" },
}),
);
});Raw lines 28 to 64as Type → fromPartial()
Before:
getUser({ body: { id: "123" } } as Request);After:
import { fromPartial } from "@total-typescript/shoehorn";
getUser(fromPartial({ body: { id: "123" } }));Raw lines 65 to 80as 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 } }));Raw lines 81 to 96When 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?
- 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
From mattpocock/skills at 4ae2317, 2026-10-31. Skills read by DeepSeek V4.1 Flash on 2026-11-04. Summary and techniques by Claude Opus 5.5 on 2026-11-06.