skillmake
← marketplace
engineerslibrarysha:d5063ddcd9478e86manual

mp-migrate-to-shoehorn

Use when refactoring TypeScript TEST files away from `as` type assertions to @total-typescript/shoehorn — fromPartial() for partial type-safe data, fromAny() for intentionally-wrong inputs.

One-line install
curl --create-dirs -fsSL https://skillmake.xyz/i/mp-migrate-to-shoehorn -o ~/.claude/skills/mp-migrate-to-shoehorn/SKILL.md

The hash above pins this exact content. The file we serve at /api/marketplace/mp-migrate-to-shoehorn-d5063ddc/raw always matches sha:d5063ddcd9478e86.

4,324 chars · ~1,081 tokens
---
name: mp-migrate-to-shoehorn
description: Use when refactoring TypeScript TEST files away from `as` type assertions to @total-typescript/shoehorn — fromPartial() for partial type-safe data, fromAny() for intentionally-wrong inputs.
source: https://github.com/mattpocock/skills/blob/main/skills/misc/migrate-to-shoehorn/SKILL.md
generated: 2026-05-12T18:05:10.811Z
category: library
audience: engineers
---

## When to use

- Test code is full of `as Request`, `as User`, `as unknown as X` and you want type-safe partial fixtures instead
- Passing only a few properties from a large object type into a function-under-test
- Deliberately injecting wrong-shaped data to test error paths, without losing autocomplete
- Auditing test files for `as` assertions across a codebase with a single grep

## Key concepts

### shoehorn is tests-only

@total-typescript/shoehorn is for TEST code. Never use it in production code — you lose the type safety that justified writing TypeScript in the first place. Matt is explicit about this.

### why `as` is a smell in tests

`as Type` forces TypeScript to trust you, must specify target type manually, and the double-as pattern (`as unknown as Type`) for intentionally wrong data is ugly. Shoehorn keeps the IDE helpful while letting you pass partials.

### fromPartial()

Pass partial data that still type-checks against the full type. Use for the common case: you only care about a few properties of a large input.

### fromAny()

Pass intentionally wrong data — e.g. `{ body: { id: 123 } }` where the type wants `id: string`. Keeps autocomplete on the surrounding object while waving through the deliberately-wrong field. Replaces `as unknown as Type`.

### fromExact()

Force a full object (every property must be present). Useful as a step before refactoring to fromPartial later — you can ratchet the test from 'must be exact' to 'partial is fine' as the type stabilises.

## API reference

```
Install
```

Single dev dependency.

```
npm i @total-typescript/shoehorn
```

```
fromPartial — replace `as Type`
```

Most common migration. Pass only what the test cares about.

```
import { fromPartial } from "@total-typescript/shoehorn";

it("gets user by id", () => {
  getUser(
    fromPartial({
      body: { id: "123" },
    }),
  );
});
```

```
fromAny — replace `as unknown as Type`
```

When you're feeding the function deliberately-wrong data to test error handling.

```
import { fromAny } from "@total-typescript/shoehorn";

getUser(fromAny({ body: { id: 123 } }));
```

```
Migration grep
```

Find every TypeScript test file using `as` type assertions in one go.

```
grep -r " as [A-Z]" --include="*.test.ts" --include="*.spec.ts"
```

```
Workflow checklist
```

Steps to run in order. Type-check at the end catches mismatched migrations.

```
[ ] Install: npm i @total-typescript/shoehorn
[ ] Find test files with `as` assertions (grep above)
[ ] Replace `as Type` → fromPartial()
[ ] Replace `as unknown as Type` → fromAny()
[ ] Add imports from @total-typescript/shoehorn
[ ] Run tsc --noEmit to verify
```

## Gotchas

- TESTS ONLY. Don't sneak shoehorn into production code — it bypasses the type system on purpose.
- `fromPartial` requires the type to be inferrable from the call site. If the function signature uses generics, you may need to annotate.
- `fromAny` keeps autocomplete on the SURROUNDING object, not on the deliberately-wrong field. The wrong field is still 'any'.
- If a test was passing because `as` silenced a real bug, the shoehorn migration will surface it — that's a win, not a regression.
- Watch for `as const` — that's a different construct (literal type assertion) and should NOT be migrated to shoehorn.
- After migration, run the full tsc --noEmit, not just per-file. Type errors can propagate from helpers that consumed the old `as` shapes.
- fromExact is rarely the right starting point — prefer fromPartial unless the test needs exhaustive shape verification.
- If you're on a non-TS test framework or your tests live alongside production code, scoping shoehorn correctly takes more care — keep the dependency in devDependencies.

---
Generated by SkillMake from https://github.com/mattpocock/skills/blob/main/skills/misc/migrate-to-shoehorn/SKILL.md on 2026-05-12T18:05:10.811Z.
Verify against source before relying on details.

File: ~/.claude/skills/mp-migrate-to-shoehorn/SKILL.md