mcpField
T
type-display-attention

type-display-attention

github.com/marius-townhouse开发643 次安装38 周前更新
代码仓库

关于 type-display-attention

面向 TypeScript 开发者的技能,讲解如何让复杂类型在 IDE 提示和错误信息中保持易读,并介绍类型别名与恒等映射类型等方法。

主要功能

  1. 01改善类型在 IDE 中的可读性
  2. 02用别名整理复杂类型
  3. 03使用恒等映射类型
  4. 04检查提示与错误信息

适用场景

  1. 01理清深层嵌套类型的显示
  2. 02提升泛型公共 API 的可读性
  3. 03排查难懂的类型错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill type-display-attention

安装后在 Claude Code 中输入/type-display-attention确认已加载。

详细介绍

注意类型的显示方式

概述

你编写的类型不仅是给编译器用的,也是给在 IDE 中阅读代码的开发者看的。复杂类型可能会展开成难以阅读的内容,让含义变得模糊,损害开发体验。了解如何控制类型的显示方式,可以帮助你创建既正确又易读的类型。

类型显示方式会影响调试、API 易用性和整体开发效率。类型即使能正常工作,如果显示效果不佳,也会造成阻碍。

何时使用此技能

  • 复杂类型在悬停提示中显示不佳
  • 用户看到的是展开后的类型,而不是类型名称
  • 调试令人困惑的类型错误
  • 使用泛型类型构建公共 API
  • 类型变得深度嵌套或具有递归结构

铁律

使用类型别名和恒等映射类型来控制类型的显示方式。确保类型在 IDE 的工具提示和错误消息中易于阅读。

检测

留意以下显示问题:

// UGLY DISPLAY - Users see this expansion:
// { [K in keyof T as ToCamel<K & string>]: T[K] }
// Instead of a clean name

// CONFUSING ERROR - Type displays as:
// { a: { b: { c: { d: string } } } }
// Instead of: DeepNested<string>

恒等映射类型技巧

强制 TypeScript 保留类型别名:

// Without trick - displays as expansion
type ObjectToCamel<T> = {
  [K in keyof T as ToCamel<K & string>]: T[K]
};

const result = objectToCamel({ foo_bar: 1 });
// Hover shows: { [K in keyof T as ToCamel<... 

// With identity mapped type - displays as name
type ObjectToCamel<T> = {
  [K in keyof T as ToCamel<K & string>]: T[K]
} extends infer O 
  ? { [K in keyof O]: O[K] } 
  : never;

const result = objectToCamel({ foo_bar: 1 });
// Hover shows: ObjectToCamel<{ foo_bar: number }>

创建清晰的类型别名

// BAD: Complex inline type
function processData(
  input: { [K in keyof User as `set${Capitalize<K & string>}`]: User[K] }
): void;

// GOOD: Named type alias
type SetterMethods<T> = {
  [K in keyof T as `set${Capitalize<K & string>}`]: T[K]
};

function processData(input: SetterMethods<User>): void;
// Displays as: SetterMethods<User>

简化复杂的返回类型

// Complex generic return type
type QueryResult<T> = T extends { data: infer D }
  ? D extends Array<infer Item>
    ? PaginatedResult<Item>
    : SingleResult<D>
  : ErrorResult;

// Simplify display with intermediate type
type QueryResult<T> = T extends { data: infer D }
  ? QueryResultHelper<D>
  : ErrorResult;

type QueryResultHelper<D> = D extends Array<infer Item>
  ? PaginatedResult<Item>
  : SingleResult<D>;

隐藏实现细节

// Internal complex type
type InternalTransform<T> = /* complex 10-line type */;

// Public clean type
type PublicType<T> = InternalTransform<T> extends infer R
  ? { [K in keyof R]: R[K] }
  : never;

// Users see: PublicType<T>
// Not the messy InternalTransform expansion

在联合类型中保留类型名称

// Each branch keeps its name
type Result<T> = 
  | { type: 'success'; data: T }
  | { type: 'error'; error: Error }
  | { type: 'loading' };

// Displays cleanly as:
// Result<User> = 
//   | { type: 'success'; data: User }
//   | { type: 'error'; error: Error }
//   | { type: 'loading' }

测试类型显示

检查类型在实际使用中的显示效果:

// Create test cases to see how types display
type TestCase1 = YourComplexType<{ a: string }>;
// Hover over TestCase1 to see display

type TestCase2 = YourComplexType<{ nested: { deep: number } }>;
// Check nested case

// Check error messages
const x: TestCase1 = {} as any;
// Trigger an error to see how type appears in message

IDE 特定注意事项

不同 IDE 对类型的显示方式各不相同:

// VS Code: Hover to see type
type Example = /* your type */;

// Check in:
// - Hover tooltips
// - IntelliSense autocomplete
// - Error message panels
// - Quick fix suggestions

抗压应对方案

当类型显示不佳时:

  1. 检查悬停提示:查看用户实际看到的内容
  2. 引入别名:将复杂类型拆分成有名称的部分
  3. 使用恒等映射类型:强制保留类型名称
  4. 测试错误消息:确保错误中引用的是清晰的类型名称
  5. 考虑简化:类型可能过于复杂

危险信号

症状问题解决方案
类型显示为展开内容未保留别名恒等映射类型
显示内容深度嵌套层级过多中间类型别名
泛型信息冗余类型参数过多简化或使用默认值
错误中难以阅读条件类型复杂命名结果类型

常见借口

“用户可以看懂展开内容”

事实:复杂的展开内容很难阅读。清晰的名称能立即传达意图。

“这只是内部用途”

事实:同事(以及未来的你)也会阅读内部类型。清晰的显示方式能帮助所有人。

“这种类型本来就很复杂”

事实:你可以用清晰的接口隐藏复杂性。用户不需要看到所有实现细节。

快速参考

技巧语法使用场景
类型别名type Name = ...任何复杂类型
恒等映射extends infer O ? { [K in keyof O]: O[K] } : never强制保留名称
中间类型分步骤拆分多步骤转换
联合类型分支命名对象类型可辨识联合类型

总结

类型就是用户界面。使用别名和恒等映射类型控制类型的显示方式。在悬停提示和错误消息中显示易读的类型,有助于改善开发体验。

参考资料

  • Dan Vanderkam 著《Effective TypeScript》第 2 版
  • 条目 56:注意类型的显示方式

评论

支持 Markdown