← AskMattCONTENT HISTORY

Update to AskMatt

Snapshot Sep 30, 2026 · 23:16 UTC · version 2.0.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "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.",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 110
    }
  ],
  "skill_md_contents": "---\nname: migrate-to-shoehorn\ndescription: 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.\ndisable-model-invocation: true\n---\n\n# Migrate to Shoehorn\n\n## Why shoehorn?\n\n`shoehorn` lets you pass partial data in tests while keeping TypeScript happy. It replaces `as` assertions with type-safe alternatives.\n\n**Test code only.** Never use shoehorn in production code.\n\nProblems with `as` in tests:\n\n- Trained not to use it\n- Must manually specify target type\n- Double-as (`as unknown as Type`) for intentionally wrong data\n\n## Install\n\n```bash\nnpm i @total-typescript/shoehorn\n```\n\n## Migration patterns\n\n### Large objects with few needed properties\n\nBefore:\n\n```ts\ntype Request = {\n  body: { id: string };\n  headers: Record<string, string>;\n  cookies: Record<string, string>;\n  // ...20 more properties\n};\n\nit(\"gets user by id\", () => {\n  // Only care about body.id but must fake entire Request\n  getUser({\n    body: { id: \"123\" },\n    headers: {},\n    cookies: {},\n    // ...fake all 20 properties\n  });\n});\n```\n\nAfter:\n\n```ts\nimport { fromPartial } from \"@total-typescript/shoehorn\";\n\nit(\"gets user by id\", () => {\n  getUser(\n    fromPartial({\n      body: { id: \"123\" },\n    }),\n  );\n});\n```\n\n### `as Type` → `fromPartial()`\n\nBefore:\n\n```ts\ngetUser({ body: { id: \"123\" } } as Request);\n```\n\nAfter:\n\n```ts\nimport { fromPartial } from \"@total-typescript/shoehorn\";\n\ngetUser(fromPartial({ body: { id: \"123\" } }));\n```\n\n### `as unknown as Type` → `fromAny()`\n\nBefore:\n\n```ts\ngetUser({ body: { id: 123 } } as unknown as Request); // wrong type on purpose\n```\n\nAfter:\n\n```ts\nimport { fromAny } from \"@total-typescript/shoehorn\";\n\ngetUser(fromAny({ body: { id: 123 } }));\n```\n\n## When to use each\n\n| Function        | Use case                                           |\n| --------------- | -------------------------------------------------- |\n| `fromPartial()` | Pass partial data that still type-checks           |\n| `fromAny()`     | Pass intentionally wrong data (keeps autocomplete) |\n| `fromExact()`   | Force full object (swap with fromPartial later)    |\n\n## Workflow\n\n1. **Gather requirements** - ask user:\n   - What test files have `as` assertions causing problems?\n   - Are they dealing with large objects where only some properties matter?\n   - Do they need to pass intentionally wrong data for error testing?\n\n2. **Install and migrate**:\n   - [ ] Install: `npm i @total-typescript/shoehorn`\n   - [ ] Find test files with `as` assertions: `grep -r \" as [A-Z]\" --include=\"*.test.ts\" --include=\"*.spec.ts\"`\n   - [ ] Replace `as Type` with `fromPartial()`\n   - [ ] Replace `as unknown as Type` with `fromAny()`\n   - [ ] Add imports from `@total-typescript/shoehorn`\n   - [ ] Run type check to verify\n"
}

SHA-256: f48be1ec7c6eaf99f1a75053d214c1b01104cebb97c4ff83480e8fb14dd08e9a