mcpField
E
ecmascript-over-typescript-features

ecmascript-over-typescript-features

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

关于 ecmascript-over-typescript-features

这项 TypeScript 技能建议运行时代码优先使用标准 ECMAScript 功能,而非 `enum`、`namespace` 等 TypeScript 专属结构。它面向希望编写可移植 JavaScript 模式、同时继续使用 TypeScript 类型系统的开发者。

主要功能

  1. 01优先采用 ECMAScript 运行时功能
  2. 02用常量对象替代枚举
  3. 03用 ES 模块替代命名空间
  4. 04显式声明类属性
  5. 05区分仅类型与运行时功能

适用场景

  1. 01选择枚举的替代写法
  2. 02使用标准模块组织代码
  3. 03编写兼顾 JavaScript 可移植性的库

安装

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

$npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill ecmascript-over-typescript-features

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

详细介绍

优先使用 ECMAScript 特性,而非 TypeScript 特性

概述

TypeScript 包含 enum 和 namespace 等 JavaScript 中不存在的专属特性。尽可能优先使用标准 ECMAScript 特性——它们的可移植性更好,也更容易被 JavaScript 生态理解,而且不会让你受限于 TypeScript 专属模式。

这并不意味着要完全避免 TypeScript——请充分使用它的类型系统。但对于运行时特性,应优先选择标准 JavaScript。

何时使用此技能

  • 在 TypeScript 和 ECMAScript 特性之间进行选择
  • 编写可能在没有 TypeScript 的环境中使用的可移植代码
  • 考虑使用 enum、namespace 或参数属性
  • 面向多个 JavaScript 环境
  • 编写供广泛使用的库代码

铁律

优先使用标准 ECMAScript 特性,而非 TypeScript 专属的运行时特性。类型使用 TypeScript,运行时行为使用 JavaScript。

检测

留意 TypeScript 专属的运行时特性:

// RED FLAGS - TypeScript-specific features
enum Status { Active, Inactive }  // TypeScript enum
namespace MyLib { }               // TypeScript namespace
class Foo { constructor(public x: number) {} }  // Parameter properties

枚举:改用常量对象

// TypeScript enum - generates runtime code
enum Status {
  Active = 'ACTIVE',
  Inactive = 'INACTIVE',
}
// Generates: var Status = { Active: 'ACTIVE', ... }

// BETTER: Const object with type
const Status = {
  Active: 'ACTIVE',
  Inactive: 'INACTIVE',
} as const;

type Status = typeof Status[keyof typeof Status];
// Status = 'ACTIVE' | 'INACTIVE'

// Usage
function setStatus(status: Status) { }
setStatus(Status.Active);  // OK
setStatus('ACTIVE');       // OK
setStatus('INVALID');      // Error!

命名空间:改用 ES 模块

// TypeScript namespace
namespace Utils {
  export function formatDate(d: Date): string {
    return d.toISOString();
  }
  export const PI = 3.14159;
}

// BETTER: ES Module
// utils.ts
export function formatDate(d: Date): string {
  return d.toISOString();
}
export const PI = 3.14159;

// usage.ts
import { formatDate, PI } from './utils';

参数属性:明确声明

// TypeScript parameter properties
class Person {
  constructor(
    public name: string,
    private age: number,
    protected id: string
  ) {}
}

// BETTER: Explicit declarations
class Person {
  name: string;
  private age: number;
  protected id: string;
  
  constructor(name: string, age: number, id: string) {
    this.name = name;
    this.age = age;
    this.id = id;
  }
}

何时可以使用 TypeScript 特性

// Type-only features are fine - no runtime impact
type User = { name: string };  // TypeScript type
interface Config { }           // TypeScript interface
type ID = string;              // Type alias

// These compile away completely!

抵御压力的准则

选择特性时:

  1. 先问:这是否仅用于类型? TypeScript 类型很好用。
  2. 检查运行时影响:它会生成特殊代码吗?
  3. 考虑可移植性:没有 TypeScript 时也能运行吗?
  4. 优先选择标准特性:ECMAScript 特性无处不在。
  5. 说明例外情况:如果必须使用 TS 特性,请解释原因。

危险信号

反模式问题解决方案
用 enum 表示字符串联合类型TypeScript 专属,会生成代码as const 对象
namespaceTypeScript 专属模块系统ES 模块
参数属性TypeScript 专属语法显式声明属性

常见的自我辩解

“枚举用起来更方便”

事实:使用 as const 的常量对象能提供同等的类型安全性,同时采用标准 JavaScript。

“命名空间能整理代码”

事实:ES 模块才是标准。使用文件和导入来整理代码。

“参数属性能少写代码”

事实:它们不是标准语法。显式声明属性更清晰,也更具可移植性。

快速参考

不要使用改用原因
enumas const 对象标准 JavaScript
namespaceES 模块标准特性,树摇效果更好
参数属性显式声明属性更清晰、符合标准
import =ES 导入标准模块系统

总结

使用 TypeScript 的类型系统,但运行时代码应优先采用标准 ECMAScript 特性。这样能让代码更具可移植性、更容易被理解,也更经得起未来变化。

参考

  • Dan Vanderkam 著《Effective TypeScript》第 2 版
  • 第 72 条:优先使用 ECMAScript 特性,而非 TypeScript 特性

评论

支持 Markdown