mcpField
T
typescript-variables

typescript-variables

github.com/mkosir开发7854.0k 次安装8 周前更新
代码仓库

关于 typescript-variables

为 TypeScript 变量编写提供风格指导,供开发者在当前任务中应用、审查或解释相关约定。内容涵盖常量断言、联合类型,以及 null 与 undefined 的使用。

主要功能

  1. 01按任务应用变量约定
  2. 02优先使用常量断言
  3. 03倾向字面量联合类型
  4. 04避免用多个布尔标志表示状态
  5. 05区分 null 与 undefined

适用场景

  1. 01为常量对象和数组保留字面量类型
  2. 02用联合类型表示互斥状态
  3. 03明确表达值缺失或为空

安装

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

$npx skills add https://github.com/mkosir/typescript-style-guide --skill typescript-variables

安装后在 Claude Code 中输入/typescript-variables确认已加载。

详细介绍

变量

在当前任务中应用 TypeScript 风格指南的变量约定。

工作流

  1. 检查使用方代码库的约定和配置。
  2. 显式的代码库约定优先于本指南中的主观建议。
  3. 仅应用、审查或说明与任务相关的指南。
  4. 当合适的选择取决于上下文或判断时,说明重要的权衡。

边界

  • 由 TypeScript 和 ESLint 负责自动检查它们能够强制执行的规则。
  • 不要仅仅因为启用了此技能,就引入无关的 TypeScript 风格指南约定。

相关指南

应用状态

有关需要不同数据的状态的详细指南,请在可用时使用 typescript-discriminated-unions。

变量

Const 断言

尽量使用 const 断言 as const 声明常量:

常量用于表示不会更改的值,确保代码库的可靠性和一致性。Const 断言会保留字面量类型,并推断只读属性。

  • 类型收窄 - 使用 as const 可确保字面量值(例如数字、字符串)被视为确切值,而非 number 或 string 等泛化类型。
  • 只读属性 - 对象和数组会获得只读属性,因此 TypeScript 可以捕获直接修改。

示例:

  • 对象

    // ❌ Avoid
    const FOO_LOCATION = { x: 50, y: 130 }; // Type { x: number; y: number; }
    FOO_LOCATION.x = 10;
    
    // ✅ Use
    const FOO_LOCATION = { x: 50, y: 130 } as const; // Type '{ readonly x: 50; readonly y: 130; }'
    FOO_LOCATION.x = 10; // Error
    
  • 数组

    // ❌ Avoid
    const BAR_LOCATION = [50, 130]; // Type number[]
    BAR_LOCATION.push(10);
    
    // ✅ Use
    const BAR_LOCATION = [50, 130] as const; // Type 'readonly [50, 130]'
    BAR_LOCATION.push(10); // Error
    
  • 模板字面量

    // ❌ Avoid
    const RATE_LIMIT = 25;
    const RATE_LIMIT_MESSAGE = `Max number of requests/min is ${RATE_LIMIT}.`; // Type string
    
    // ✅ Use
    const RATE_LIMIT = 25;
    const RATE_LIMIT_MESSAGE = `Max number of requests/min is ${RATE_LIMIT}.` as const; // Type 'Max number of requests/min is 25.'
    
枚举与 Const 断言

TypeScript 生态系统不建议使用枚举,因为它们会带来运行时开销和一些怪异行为。
TypeScript 文档列出了若干陷阱,而 TypeScript 5.8 引入了 --erasableSyntaxOnly 标志,可彻底禁用枚举等会生成运行时代码的功能。

{'no-restricted-syntax': [ 'error', { selector: 'TSEnumDeclaration', message: 'Replace enum with a literal type or a const assertion.', }, ]}

一般来说,优先选择:

  • 尽可能使用字面量类型。
  • 循环遍历值时使用 Const 断言数组。
  • 枚举任意值时使用 Const 断言对象。

示例:

  • 使用字面量类型,避免运行时对象并减小打包体积。

    // ❌ Avoid using enums as they increase the bundle size
    enum UserRole {
      GUEST = 'guest',
      MODERATOR = 'moderator',
      ADMINISTRATOR = 'administrator',
    }
    
    // Transpiled JavaScript
    ('use strict');
    var UserRole;
    (function (UserRole) {
      UserRole['GUEST'] = 'guest';
      UserRole['MODERATOR'] = 'moderator';
      UserRole['ADMINISTRATOR'] = 'administrator';
    })(UserRole || (UserRole = {}));
    
    // ✅ Use literal types - Types are stripped during transpilation
    type UserRole = 'guest' | 'moderator' | 'administrator';
    
    const isGuest = (role: UserRole) => role === 'guest';
    
  • 循环遍历值时使用 Const 断言数组。

    // ❌ Avoid using enums
    enum USER_ROLES {
      guest = 'guest',
      moderator = 'moderator',
      administrator = 'administrator',
    }
    
    // ✅ Use const assertions arrays
    const USER_ROLES = ['guest', 'moderator', 'administrator'] as const;
    type UserRole = (typeof USER_ROLES)[number];
    
    const seedDatabase = () => {
      USER_ROLES.forEach((role) => {
        db.roles.insert(role);
      }
    }
    const insert = (role: UserRole) => {...
    
    const UsersRoleList = () => {
      return (
        <div>
          {USER_ROLES.map((role) => (
            <Item key={role} role={role} />
          ))}
        </div>
      );
    };
    const Item = ({ role }: { role: UserRole }) => {...
    
  • 枚举任意值时使用 Const 断言对象。

    // ❌ Avoid using enums
    enum COLORS {
      primary = '#B33930',
      secondary = '#113A5C',
      brand = '#9C0E7D',
    }
    
    // ✅ Use const assertions objects
    const COLORS = {
      primary: '#B33930',
      secondary: '#113A5C',
      brand: '#9C0E7D',
    } as const;
    
    type Colors = typeof COLORS;
    type ColorKey = keyof Colors; // Type "primary" | "secondary" | "brand"
    type ColorValue = Colors[ColorKey]; // Type "#B33930" | "#113A5C" | "#9C0E7D"
    
    const setColor = (color: ColorValue) => {...
    
    setColor(COLORS.primary);
    setColor('#B33930');
    
类型联合与布尔标志

应使用类型联合,尤其是在类型联合选项互斥时,而不是使用多个布尔标志变量。

布尔标志往往会随着时间不断累积,导致代码令人困惑且容易出错,因为它们掩盖了应用的实际状态。

// ❌ Avoid introducing multiple boolean flag variables
const isPending, isProcessing, isConfirmed, isExpired;

// ✅ Use type union variable
type UserStatus = 'pending' | 'processing' | 'confirmed' | 'expired';
const userStatus: UserStatus;

如果只有状态值发生变化,请使用字面量联合。如果每种状态需要不同的数据,请使用判别联合显式表示有效状态。

Null 与 Undefined

启用 strictNullChecks 后,null 和 undefined 是不同的类型,含义也不同。请根据缺失在应用中的含义一致地使用它们。
尽量遵循以下规则:

  • 当值明确为空时(例如赋值或函数返回值),使用 null。
  • 当值缺失或省略时(例如表单、请求负载或数据库查询中的可选字段),使用 undefined(Prisma 的区分说明)。

评论

支持 Markdown