Skip to main content
skill · Claude Code

migrate-to-shoehorn — Claude Code skill: test migration

Replaces `as` type assertions in tests with helpers from `@total-typescript/shoehorn`. Use it when tests need partial objects or deliberately invalid data.

  • Author Matt Pocock
  • License MIT
  • GitHub ★ 302,251
  • Installs 475,388
  • Updated 2026-10-22
  • Source shown below
Open on GitHub ↗

What migrate-to-shoehorn does

The skill finds as assertions in test files and moves them to Shoehorn helpers. It replaces as Type with fromPartial(), so a test can pass only the fields it needs.

For deliberately incorrect values, it uses fromAny(). The migration adds imports from @total-typescript/shoehorn and calls for a type check afterwards. fromExact() is available when a test must start with a full object before switching to fromPartial().

Shoehorn belongs in test code only. Install this skill if your tests are full of mocked fields or as unknown as Type casts; skip it for production code.

What it helps with

  • replace as Type with fromPartial() in tests
  • pass selected fields from a large object
  • test invalid input with fromAny()
  • find assertions in *.test.ts and *.spec.ts files
  • add @total-typescript/shoehorn imports

How to install migrate-to-shoehorn

Command from the source

/plugin marketplace add mattpocock/skills

Command from the source

/plugin install mattpocock-skills@mattpocock

Command from the source

npx skills add mattpocock/skills --skill migrate-to-shoehorn -a claude-code

With the Skills CLI (Vercel)

npx skills add mattpocock/skills --skill migrate-to-shoehorn -a claude-code

Manually

~/.claude/skills/migrate-to-shoehorn/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/migrate-to-shoehorn/

How to use it: example prompts

  • “Find `as Request` in the tests and migrate it to shoehorn.”
  • “Replace `as unknown as Type` in `*.spec.ts` with `fromAny()`.”
  • “I need to pass a partial Request in a test without filling every field.”

Source text

SKILL.md · MIT
---
name: migrate-to-shoehorn
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.
---

# 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

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

## Migration patterns

### Large objects with few needed properties

Before:

```ts
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:

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

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

### `as Type` → `fromPartial()`

Before:

```ts
getUser({ body: { id: "123" } } as Request);
```

After:

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

getUser(fromPartial({ body: { id: "123" } }));
```

### `as unknown as Type` → `fromAny()`

Before:

```ts
getUser({ body: { id: 123 } } as unknown as Request); // wrong type on purpose
```

After:

```ts
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

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?

2. **Install and migrate**:
   - [ ] 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

© Matt Pocock · MIT · mattpocock/skills

Questions about migrate-to-shoehorn

How do I install migrate-to-shoehorn in Claude Code?

Add the skill with npx skills add mattpocock/skills --skill migrate-to-shoehorn -a claude-code.

What does migrate-to-shoehorn do?

It migrates test type assertions written with as to helpers from @total-typescript/shoehorn. The skill separates partial test data from deliberately invalid values.

When should I use fromPartial(), fromAny(), or fromExact()?

Use fromPartial() for incomplete data that still type-checks. Use fromAny() for intentionally wrong test input, while fromExact() requires a full object.

Similar

See also

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor