migrate-to-shoehorn rewrites TypeScript tests that use as type assertions (casts that tell TypeScript "trust me, this is that type"). In their place it uses Matt's library, @total-typescript/shoehorn, which lets a test pass partial data while keeping TypeScript happy.
The Skill names three problems with as in tests. You're trained not to use it. You must name the target type by hand. And passing wrong data on purpose needs a double cast, as unknown as Type.
It swaps the cast for the shoehorn helper that says what the test means:
as Type becomes fromPartial(), for partial data that still type-checks.
as unknown as Type becomes fromAny(), for wrong data on purpose, with autocomplete kept.
One rule is firm: test code only, never production code.
the cast
the shoehorn helper
partial data
as Type
fromPartial()
wrong data on purpose
as unknown as Type
fromAny()
test code only, never production code.
It swaps the cast for the shoehorn helper
When to use it
Your TypeScript tests fake a whole big object, such as a request with 20 more properties, when the test only cares about body.id.
Your test files are full of as casts you want gone.
Your error tests pass wrong-shaped data with as unknown as Type.
You mention shoehorn, or ask for partial test data.
When not to use it
To write new tests, or build a feature test-first, use its look-alike tdd. tdd writes new tests one slice at a time. migrate-to-shoehorn only rewrites how existing tests build their fake data.
In production code, never.
If you own the type and a function asks for far more than it uses, reshape the interface with codebase-design. Its rule: fewer params, simpler test setup.
For Python tests. It only searches *.test.ts and *.spec.ts files.
What it needs to start
A TypeScript project that installs with npm.
Your answers to three questions it asks first: which test files have as assertions causing problems, whether large objects are involved where only some properties matter, and whether you need wrong data on purpose for error tests.
A type check to run at the end.
What it creates
@total-typescript/shoehorn, installed with npm i.
Edited test files: each cast replaced, and the shoehorn imports added.
A type check run, the last step of its checklist. That's where it stops.
Going deeper
5 min read · Going deeper not read
Why it exists
The library came years before the Skill. Matt released shoehorn in 2023. In his Total TypeScript article introducing it (the page shows no date; shoehorn's v0.1.0 release is dated 11 April 2023), he says where it came from: "I've been through dozens of open-source application codebases, and all of them who used a large test suite had this problem."
Matt's article introducing shoehorn: Testing with TypeScript is Painful: Here's a Solution. From totaltypescript.com, 30 October 2026.
The problem was tests. To test a function that takes a big type, such as an express Request, you either fake every field or write as unknown as Request. On top of that, you import the type into every test. He called it "A thousand tiny cuts."
The Skill came on 3 February 2026, in a commit titled "Added migrate to shoehorn script". It teaches an agent to do that clean-up for you.
Today it sits in Matt's misc bucket, which his README describes as "Tools I keep around but rarely use, not promoted in the plugin." On 1 July 2026 he made the bucket officially non-promoted. The commit says its Skills "are no longer installable via the plugin", though "plugin.json already omitted misc". His note on the bucket, added on 6 October 2026, calls these Skills frozen: "Bug reports, feature requests and PRs against them are closed."
Citations (68)
From snapshot/skills/migrate-to-shoehorn/SKILL.md, line 3: “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.”
shoehorn's README says it gives you "first-class primitives for safely providing incomplete data to tests". It describes each helper:
fromPartial "Lets you pass a deep partial to a slot expecting a type." Deep partial means any field, nested ones too, can be left out. The fields you do give are still checked: "It'll fail if you pass a type that doesn't match the one expected".
fromAny "Lets you pass anything to a slot, while still giving you autocomplete on the original type". It checks nothing: "It WILL NOT FAIL if you pass something that doesn't match."
fromExact forces you to pass every property. The README calls it "Useful for when you want to swap in and out of fromPartial/fromAny".
The Skill's table lists all three, but its checklist only ever writes fromPartial() and fromAny().
Its search covers only --include="*.test.ts" --include="*.spec.ts", so a React test ending in .test.tsx is never found. And its plain npm i @total-typescript/shoehorn "saves any specified packages into dependencies by default", says npm, not into devDependencies.
Why is bending types allowed in tests at all? Matt's article introducing shoehorn gives the reasoning behind keeping it to tests: "Tests don't need to live up to the same level of strictness as the rest of your application code." In your app, a broken type can reach users as a bug.
The README is honest about the cost, too: "Having to pass huge objects to tests is a sign that your types are too loose. Ideally, every function should only specify the data it needs." It names two cases where shoehorn is still the best choice: legacy codebases you may not have time to refactor, and third-party libraries whose types you can't change without wrapper functions.
A real example
In June 2023, a user reported that fromPartial "seems to work perfectly for replacing every type-cast in our test suite" except for one type, AxiosInstance. Matt replied: "It looks like AxiosInstance is a function? One with multiple overloads." While Matt looked into it, the user wrote: "It's been integral to me removing hundreds of casts!" Matt fixed it the next day, closing the issue through a pull request, and wrote: "Fixed in 0.1.1".
Where it goes wrong
fromPartial can choke on huge, self-referencing types. An open issue from 5 October 2026 reports that passing a full value of such a type "fails with TS2321". The compiler "walks every member of T, then every member of those member types", until it hits its depth limit. In the ComfyUI frontend's test files, tsgo, the native preview of TypeScript, "reports 88 errors in 38 of them". The reporter proposed a fix and patched their own copy with pnpm patch.
The plugin doesn't load it. In May 2026, a report from an automated linter said that four misc Skills, this one included, "don't get registered and can't be invoked" when installed through the plugin. Matt answered "Yep, this is intentional".
Nobody upstream will fix the Skill. It is frozen, and bug reports against it are closed. His advice: "If one doesn't work for you, install it with skills.sh and fix your copy: the files are yours to edit." The freeze covers the Skill only. The library lives in its own repo, total-typescript/shoehorn, where the TS2321 issue is still open.
shoehorn issue #22, still open: fromPartial hits Excessive stack depth, failing with TS2321. From github.com, 30 October 2026.
Try it
In your practice project (set it up first with keeping-track's Try it step if you haven't), clean up one test in the TypeScript website.
Open a terminal in web/, the subfolder with its own package.json, and start your agent there.
Find, or write, one test that fakes a class or booking with as, where the test needs only one or two fields.
Ask the agent to migrate that test to shoehorn. When it asks its three questions, answer them. Tell it to install with npm i -D @total-typescript/shoehorn, and to search *.test.tsx files as well.
Run the type check yourself, npx tsc --noEmit. Then check that package.json lists shoehorn under devDependencies, and that nothing outside your tests imports it: grep -rn shoehorn src | grep -v test.
From snapshot/skills/migrate-to-shoehorn/SKILL.md, lines 107–110: “1. Gather requirements - ask user: - What test files have as assertions causing problems? - Are they dealing with large objects where only some properties matter? - Do they need to pass intentionally wrong data for error testing?”
From snapshot/skills/migrate-to-shoehorn/SKILL.md, lines 113–118: “- [ ] Install: npm i @total-typescript/shoehorn - [ ] Find test files with as assertions: grep -r " as [A-Z]" --include="*.test.ts" --include="*.spec.ts" - [ ] Replace as Type with fromPartial() - [ ] Replace as unknown as Type with fromAny() - [ ] Add imports from @total-typescript/shoehorn - [ ] Run type check to verify”
From snapshot/skills/migrate-to-shoehorn/SKILL.md, lines 101–103: “| fromPartial() | Pass partial data that still type-checks | | fromAny() | Pass intentionally wrong data (keeps autocomplete) | | fromExact() | Force full object (swap with fromPartial later) |”
From snapshot/web/github.com/total-typescript-shoehorn.md, lines 69–72: “There are many cases where shoehorn is the best choice: - Legacy codebases: If you're working on a large codebase, you might not have the time to refactor everything to be perfect. - Third-party libraries: If you're using a third-party library, you might not be able to alter the types without needless wrapper functions.”
From snapshot/skills/migrate-to-shoehorn/SKILL.md, lines 107–110: “1. Gather requirements - ask user: - What test files have as assertions causing problems? - Are they dealing with large objects where only some properties matter? - Do they need to pass intentionally wrong data for error testing?”