migrate-to-shoehorn
vinvcn/mattpocock-skills-zh-cn
Migrate TypeScript test assertions from `as` to type-safe @total-typescript/shoehorn helpers.
What is migrate-to-shoehorn?
Replace unsafe `as` type assertions in test files with shoehorn's `fromPartial()` and `fromAny()` functions. Use this when you need to pass partial test data while maintaining TypeScript type safety, or when dealing with large objects where only a few properties matter.
- Replace `as Type` assertions with `fromPartial()` for partial data that still type-checks
- Replace `as unknown as Type` assertions with `fromAny()` for intentionally wrong test data
- Eliminate the need to fake all properties on large objects—only specify what matters
- Maintain autocomplete and type hints even when passing incomplete or incorrect data
- Provide `fromExact()` for enforcing full object structure when needed
How to install migrate-to-shoehorn
npx skills add https://github.com/vinvcn/mattpocock-skills-zh-cn --skill migrate-to-shoehorn- npm i @total-typescript/shoehorn
How to use migrate-to-shoehorn
- 1.Identify test files containing `as Type` or `as unknown as Type` assertions (use grep or search)
- 2.Replace `as Type` with `fromPartial({...})` imported from @total-typescript/shoehorn
- 3.Replace `as unknown as Type` with `fromAny({...})` for intentionally incorrect data
- 4.Add import statement: `import { fromPartial, fromAny } from '@total-typescript/shoehorn'`
- 5.Run TypeScript type check to verify migrations are correct
Use cases
- Testing a function that accepts a large Request object but only needs the body.id property
- Passing intentionally malformed data to test error-handling paths without double-as casts
- Reducing test boilerplate when mocking complex types with many optional or unused fields
- Migrating an existing test suite away from unsafe type assertions
- Ensuring test data changes don't silently break type safety
- TypeScript developers writing unit tests
- Teams migrating legacy test code with `as` assertions
- QA engineers building type-safe test fixtures
- Projects using @total-typescript tooling
migrate-to-shoehorn FAQ
No. Shoehorn is designed only for test code. Never use it in production.
Use `fromPartial()` when passing partial data that still type-checks correctly. Use `fromAny()` when you intentionally pass wrong types (e.g., id: 123 instead of id: '123') to test error paths.
Use `fromExact()` to force providing the full object structure. It's useful as a temporary step before switching to `fromPartial()` once you've identified which properties actually matter.
Run: `grep -r " as [A-Z]" --include="*.test.ts" --include="*.spec.ts"` to locate all type assertions in your test directory.
Full instructions (SKILL.md)
Source of truth, from vinvcn/mattpocock-skills-zh-cn.
name: migrate-to-shoehorn
description: 将测试文件从 as 类型断言迁移到 @total-typescript/shoehorn。适用于用户提到 shoehorn、想替换测试中的 as,或需要局部测试数据时。
Migrate to Shoehorn
Why shoehorn?
shoehorn 允许你在 tests 中传入 partial data,同时保持 TypeScript 满意。它用 type-safe alternatives 替换 as assertions。
只用于 test code。 永远不要在 production code 中使用 shoehorn。
Tests 中 as 的问题:
- 经过训练,不去使用它
- 必须手动指定 target type
- 对故意错误的数据需要 double-as(
as unknown as Type)
Install
npm i @total-typescript/shoehorn
Migration patterns
Large objects with few needed properties
Before:
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:
import { fromPartial } from "@total-typescript/shoehorn";
it("gets user by id", () => {
getUser(
fromPartial({
body: { id: "123" },
}),
);
});
as Type → fromPartial()
Before:
getUser({ body: { id: "123" } } as Request);
After:
import { fromPartial } from "@total-typescript/shoehorn";
getUser(fromPartial({ body: { id: "123" } }));
as unknown as Type → fromAny()
Before:
getUser({ body: { id: 123 } } as unknown as Request); // wrong type on purpose
After:
import { fromAny } from "@total-typescript/shoehorn";
getUser(fromAny({ body: { id: 123 } }));
When to use each
| Function | Use case |
|---|---|
fromPartial() | 传入仍能 type-check 的 partial data |
fromAny() | 传入故意错误的数据(保留 autocomplete) |
fromExact() | 强制 full object(之后可换成 fromPartial) |
Workflow
-
Gather requirements — 询问用户:
- 哪些 test files 中的
asassertions 造成问题? - 是否在处理大型 objects,但只关心部分 properties?
- 是否需要传入故意错误的数据来测试 error paths?
- 哪些 test files 中的
-
Install and migrate:
- Install:
npm i @total-typescript/shoehorn - 查找 test files 中的
asassertions:grep -r " as [A-Z]" --include="*.test.ts" --include="*.spec.ts" - 用
fromPartial()替换as Type - 用
fromAny()替换as unknown as Type - 添加来自
@total-typescript/shoehorn的 imports - 运行 type check 验证
- Install:
Related skills
More from vinvcn/mattpocock-skills-zh-cn and the wider catalog.

obsidian-vault
Search, create, and manage notes in Obsidian vault using wikilinks and index notes.

prototype
Build throwaway prototypes to validate design decisions and state models quickly.

qa
Interactive QA sessions that convert user-reported bugs into well-structured GitHub issues with codebase context.

request-refactor-plan
Create detailed refactor plans with small commits through user interviews, then submit as GitHub issues.

research
Research topics against primary sources and save findings as Markdown files in your repo.

resolving-merge-conflicts
Resolve git merge/rebase conflicts by understanding intent and preserving both sides when compatible.