关于 web-master
Web Master 是面向编写 Web 代码的 Agent 的技能,涵盖 TypeScript、CSS、HTML/JSX 和测试规范。它强调类型安全、精简样式,以及围绕可观察行为设计测试。
主要功能
- 01TypeScript 类型安全指导
- 02CSS 与排版规范
- 03精简 HTML 和 JSX
- 04基于可观察行为设计测试
- 05避免不必要模拟的指导
适用场景
- 01实现 TypeScript Web 功能
- 02调整 CSS 和排版
- 03审查组件标记
- 04编写 Web 行为测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ robot-inventor/ agent-skills --skill web-master安装后在 Claude Code 中输入/web-master确认已加载。
详细介绍
Web Master
编写 Web 相关代码时,请遵循以下说明。
TypeScript
不要使用类型断言
除非确有需要,否则不要使用类型断言。不要因为觉得以后可能会用到,就一开始先添加类型断言。只有在满足以下所有条件时,才可以使用类型断言:
- 先编写不带类型断言的代码,并遇到类型错误。
- 无法通过改进其他位置的类型定义来解决该类型错误。
- 添加类型断言不会损害类型安全。
不要使用 ReturnType
除非确有需要,否则不要使用 ReturnType。请改用以下方法。
如果你需要在项目中某个函数之外使用该函数的返回类型:
- 对于
boolean或string这样的简单原始类型,直接写出类型。 - 对于复杂类型,定义一个具名类型,将其指定为函数的返回类型(
(): T => {}),并复用T。
如果你需要使用库函数的返回类型:
- 首先检查该函数的类型定义。
- 如果该库导出了此类型,请使用导出的类型。
- 如果需要将另一个库函数的返回类型作为类型参数传入,而该库没有导出该函数的返回类型,则可以在类型参数中使用
ReturnType。
- 如果需要将另一个库函数的返回类型作为类型参数传入,而该库没有导出该函数的返回类型,则可以在类型参数中使用
- 如果该库没有导出该类型:
- 如果是简单原始类型,直接写出类型。
- 否则,可以使用
ReturnType。
// Incorrect
import foo from "foo";
const myFunc = (): string => {...};
const myFunc2 = (arg: ReturnType<typeof foo>, arg2: ReturnType<typeof myFunc>): number => {...};
// Correct
import type { FooResult } from "foo";
const myFunc = (): string => {...};
const myFunc2 = (arg: FooResult, arg2: string): number => {...};
优先使用 as const satisfies,而不是类型注解
除非确有需要,否则不要添加类型注解。从不带类型注解的代码开始编写。如果因此导致类型错误,首先尝试通过改进其他位置的类型定义来解决。只有在这些修改无法解决问题时,才将类型注解作为最后手段。
编写对象并需要确保其符合特定类型时,请使用 satisfies。对于类型显而易见的值(例如字符串数组),无需使用 satisfies。对于 as const satisfies 值的类型,无需指定 ReadOnly。
// Incorrect
const foo: T = {
bar: "bar"
};
const foo = {
bar: "bar"
} as const satisfies ReadOnly<T>;
// Correct
const foo = {
bar: "bar"
} as const satisfies T;
不要禁用 ESLint 规则
不要为了图省事而禁用 ESLint 规则。ESLint 错误通常指出的是低质量代码,而不是制造无谓的障碍。禁用规则来消除错误,会让根本问题依然存在。
只有在没有更好选择时,才将禁用 ESLint 规则作为最后手段。请按以下方式处理 ESLint 错误:
- 理解 ESLint 报告的问题。找出受影响的代码,以及该规则的目的。
- 以能够解决该问题的方式改进代码。
- 只有在遵循规则会让代码变得过于复杂、警告明显属于误报、你有其他正当理由需要禁用规则,或者可能的修复方案会与规则的根本意图冲突时,才禁用该规则。
示例
ESLint 的 sort-imports 规则规定了统一的导入顺序。在模块化良好的代码中,行为不应取决于导入顺序,因此应遵循此规则。
// Incorrect
/* eslint-disable sort-imports */
import foo from "foo";
import bar from "bar";
// Correct
import bar from "bar";
import foo from "foo";
no-magic-numbers 规则旨在为用途不明确的数值赋予有意义的名称。对于显而易见的值,例如表示一分钟秒数的 60,无需为了满足规则而强行将其设为常量。在这种情况下,可以禁用该规则。将 1 替换为名为 ONE 的常量,也违背了 no-magic-numbers 的目的。应为该值赋予有意义的名称;如果其含义已一目了然,也可以禁用该规则。此外,还应考虑是否真的需要将这个数字硬编码。
// Incorrect
// eslint-disable-next-line no-magic-numbers
if (myArray.length !== 0) {...}
// Correct
if (myArray.length) {...}
max-lines 和 max-lines-per-function 规则用于衡量代码的可读性和可维护性。违反这些规则的警告表明代码设计可能存在问题。仅仅删除换行来满足规则只是表面上的解决方案,实际上会让代码更难阅读,从而违背规则的本意。正确的做法是删除冗余代码,或妥善地重构并模块化代码。如果只是略微超出限制,且代码设计已经合理,那么应禁用这些规则,而不是删除换行或强行拆分代码。
不要自行验证
TypeScript 类型并非 JavaScript 的附加功能。以类型为核心进行设计,能让代码保持整洁、高效。类型设计得当时,除用户输入或 Web API 响应等项目边界外,通常很少需要验证。基于类型妥善设计代码后,函数的输入和输出都是可靠的,无需反复验证值。
检查项目依赖项,确认是否已安装验证库。如果已经安装,应利用该库的功能,而不是自行编写验证器。
// Incorrect
const isRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null && !Array.isArray(value);
const isParson = (value: unknown): value is Person =>
isRecord(value) && typeof value.name === "string" && typeof value.age === "number" && value.age >= 0;
isParson(externalValue) ? externalValue : "Unknown";
// Correct
import { type } from "arktype";
const Person = type({
name: "string",
age: "number >= 0"
});
const parsed = Person(externalValue);
parsed instanceof type.errors ? "Unknown" : parsed;
CSS
只定义必要的样式
编写 CSS 时,先检查项目是否加载了 CSS 重置样式,以及该样式是否应用于当前正在处理的页面或布局文件。如果已应用 CSS 重置样式,就无需定义与其重叠的样式,例如 margin: 0(这只是一个示例,并不限于此)。
在 CSS 中,只应指定需要从父元素继承的属性中进行更改的属性,不需要再次更改的属性则不应指定。请记住,CSS 支持继承,并据此编写样式。
/* reset.css */
* {
margin: 0;
}
/* style.css */
/* Incorrect */
h1 {
margin: 0;
font-weight: bold;
}
h1 div {
font-weight: bold;
}
/* Correct */
h1 {
font-weight: bold;
}
有意设计字体排版
除非绝对必要(例如代码块),否则不要在文档根元素之外指定 font-family。一般来说,除非有明确理由(例如缩小不重要的提示文字或放大标题),否则不要更改字体大小。由于浏览器设置可能会覆盖基础字体大小,因此设置字体大小或依赖字体大小的区域时,请使用 em 或 rem,而不是 px。
/* Incorrect */
h1 {
font-size: 32px;
}
/* Correct */
h1 {
font-size: 2rem;
}
HTML 和 JSX
避免冗余定义
如果有可用的 UI 组件库,应积极使用其中的组件,除非绝对必要,否则尽量减少自定义实现。
此外,避免添加不必要的属性。例如,图标组件库可能默认设置了 aria-hidden;在这种情况下,使用组件时无需再次设置该属性。
测试
正确设计测试
不要模拟应用程序自有模块。优先使用真实实现,并测试可观察行为,而不是实现的连接方式。仅在速度慢、非确定性、具有破坏性或涉及外部系统的边界处使用模拟。避免编写断言仅验证模拟调用或模拟中配置值的测试。
从外部视角测试行为,而不是内部实现。换言之,重构时需要修改的测试就是糟糕的测试。测试项目代码,而不是浏览器或外部库。例如,编写代码后,按钮元素会在浏览器中显示,这是显而易见的;这测试的是浏览器的行为,而不是项目代码。
只添加必要的测试。确保测试能验证代码是否正确运行,并能检测代码出错的情况。测试本就预期会发生的结果毫无意义,而无法检测代码故障的测试毫无价值。测试代码在接收到正常、边界和异常输入值时,对外可观察到的行为。
不要为了测试而导出
不要仅为了测试而导出函数、值或其他数据。对于除测试之外不会在文件外部使用的内容,请使用源文件内测试,而不是导出它们并创建单独的测试文件。
不要模拟外部环境
对于需要访问数据库或外部服务的测试,请使用 Testcontainers,而不是模拟它们。如果需要计时器,请使用测试库提供的虚假计时器。