← AskMattCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to AskMatt
Snapshot Sep 30, 2026 · 23:16 UTC · version 2.0.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull 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