| name | typescript-standards |
| description | TypeScript 开发规范,与 ESLint 配置保持一致。包含类型定义、数组语法、类型注解等规范。 |
TypeScript 开发规范
本规范与项目 ESLint 配置保持一致,编写 TypeScript 代码时必须遵守。
目录结构
src/types/<Module>/<Module>.d.ts # 类型定义 (.d.ts)
types/<Module>/<Module>.d.ts # 根目录类型定义
src/enum/<Module>.ts # 枚举常量 (.ts)
命名规范
| 类型 | 规范 | 示例 |
|---|
| Interface/Type | PascalCase | UserProfile |
| const 对象 | PascalCase | NewsType |
| type alias | PascalCase + Enum | NewsTypeEnum |
| enum 常量 | PascalCase + Enum | PostNewsTypeEnum |
| readonly 列表 | PascalCase + List | PostNewsTypeList |
| 描述函数 | camelCase + Desc | getPostNewsTypeDesc |
| 常量 | UPPER_SNAKE_CASE | MAX_RETRY_COUNT |
核心规则
1. 数组类型定义
使用 Array<T> 语法,禁止使用 T[]
const list: Array<string> = [];
const matrix: Array<Array<number>> = [];
const list: string[] = [];
const matrix: number[][] = [];
2. 类型注解与断言
优先使用类型注解 : Type,必要时使用 <Type> 断言,禁止使用 as Type
const value: string = someValue;
const count: number = getCount();
const result: string = getValue();
const el: HTMLInputElement = <HTMLInputElement>document.getElementById("id");
const data = <MyDataType>unknownValue;
function getUser(id: number): UserProfile {
return { id, name: "User" };
}
const value = someValue as string;
const result = getValue() as string;
const getUser = (id: number): UserProfile => {
return { id, name: "User" };
};
function getUser(id): UserProfile {
return { id, name: "User" };
}
3. 禁止原生 enum
使用 const 对象模式,使用 <const> 断言确保 readonly
const GameServerEnum = <const>{
CN_GF01: "cn_gf01",
CN_QD01: "cn_qd01",
};
type GameServerEnumType = (typeof GameServerEnum)[keyof typeof GameServerEnum];
enum GameServerEnum {
CN_GF01 = "cn_gf01",
CN_QD01 = "cn_qd01",
}
4. 类型定义
优先使用 type 而非 interface
type UserProfile = {
id: number;
name: string;
};
interface UserProfile {
id: number;
name: string;
}
5. 函数定义规范
优先使用 function 关键字定义函数,而不是箭头函数赋值给 const
function getUser(id: number): UserProfile {
return { id, name: "User" };
}
async function loadData(): Promise<void> {
await fetch("/api/data");
}
const getUser = (id: number): UserProfile => {
return { id, name: "User" };
};
const loadData = async (): Promise<void> => {
await fetch("/api/data");
};
例外情况(可以使用箭头函数):
- 需要捕获词法
this 时
- 作为回调函数传递给其他函数时
- 对象字面量中的方法(根据场景判断)
6. 类型注解规范
- 函数参数和返回值必须显式类型注解
- 使用
unknown 而非 any
ref 泛型必须显式声明
const count = ref<number>(0);
const list = ref<Array<string>>([]);
const isDone = ref<boolean>(false);
function getUser(id: number): UserProfile {
return { id, name: "User" };
}
const count = ref(0);
const list: string[] = ref([]);
function getUser(id): UserProfile {
return { id, name: "User" };
}
7. JSDoc 注释
- 所有导出函数必须包含
@since 标签
- 枚举常量需要
@see 标签
- 类型定义的子成员修改时,需同步更新父级类型和文件头的
@since 版本号
function getCharacter(id: number): Character;
type Character = {
id: number;
name: string;
};
版本更新规则:
当修改类型的子成员时(如添加字段),需要:
- 更新父级类型的
@since 为当前项目版本(递增)
- 如该文件是主要变更文件,同步更新文件头的
@since
示例(项目版本从 0.9.8 → 0.9.9):
type Character = {
id: number;
name: string;
};
type Character = {
id: number;
name: string;
element: string;
};
8. 枚举使用规范
在Vue组件中,必须使用类似 gameEnum 的常量枚举对象访问常量枚举值,禁止直接使用类型定义中的枚举
const statusOrder: Record<TGApp.Game.ActCalendar.PoolStatusEnum, number> = {
[gameEnum.actCalendar.poolStatus.Ongoing]: 0,
[gameEnum.actCalendar.poolStatus.NotStart]: 1,
[gameEnum.actCalendar.poolStatus.Ended]: 2,
};
const statusOrder: Record<TGApp.Game.ActCalendar.PoolStatusEnum, number> = {
[TGApp.Game.ActCalendar.PoolStatus.Ongoing]: 0,
[TGApp.Game.ActCalendar.PoolStatus.NotStart]: 1,
[TGApp.Game.ActCalendar.PoolStatus.Ended]: 2,
};
原因:
- Vue组件的模板和脚本部分需要运行时可访问的值
TGApp.Game.ActCalendar.PoolStatus 是类型定义,编译后不存在
gameEnum 是实际的JavaScript对象,可以在运行时访问
适用场景:
- Vue组件的
<script setup> 部分
- 组件的计算属性和方法中
- 模板中的条件判断和绑定
例外情况:
ESLint 规则对应
| 规则 | ESLint 配置 | 语法要求 |
|---|
| 数组类型 | @typescript-eslint/array-type | Array<T> |
| 类型断言 | @typescript-eslint/consistent-type-assertions | <Type> |
| 类型定义 | @typescript-eslint/consistent-type-definitions | type |
| 导入顺序 | import/order | 分组排序 |
详细规范