TS 写法规范
TypeScript 是 SoybeanAdmin 的开发基石,良好的类型约束能在编译阶段发现错误、提升代码的可读性与可维护性。本章节汇总了在严格模式下编写 TypeScript 的常见约定,帮助你写出类型安全、风格统一的代码。
开启严格模式
始终在 tsconfig.json 中开启 strict 模式,它会一并启用 strictNullChecks、noImplicitAny 等一系列检查,是类型安全的基础。
{
"compilerOptions": {
"strict": true
}
}优先类型推断
让编译器自动推断类型,避免冗余的类型注解。只在编译器无法推断、或需要明确约束意图时才显式标注。
// 推荐:编译器可推断为 number
const count = 1;
const list = [1, 2, 3];
// 不推荐:多余的注解
const count: number = 1;函数的返回值通常也可以推断,但对外暴露的公共 API 建议显式标注返回类型,以稳定接口契约。
interface 与 type 的取舍
两者在多数场景可以互换,约定如下:
- 描述对象结构、需要被继承或合并时,优先使用
interface。 - 表达联合类型、交叉类型、元组或工具类型时,使用
type。
// 对象结构用 interface
interface User {
id: number;
name: string;
}
// 联合 / 工具类型用 type
type Status = 'pending' | 'success' | 'failed';
type Nullable<T> = T | null;避免 any
any 会关闭类型检查,应尽量避免。当类型确实未知时,使用 unknown,并在使用前通过类型收窄缩小范围。
function parse(input: unknown) {
if (typeof input === 'string') {
// 此处 input 被收窄为 string
return input.trim();
}
return '';
}善用泛型与工具类型
用泛型抽象可复用的逻辑,用内置工具类型(Partial、Required、Pick、Omit、Record 等)从已有类型派生新类型,避免重复定义。
interface User {
id: number;
name: string;
email: string;
}
type UserPreview = Pick<User, 'id' | 'name'>;
type UserPatch = Partial<User>;
type UserMap = Record<number, User>;
function identity<T>(value: T): T {
return value;
}命名约定
类型、接口、枚举统一使用 PascalCase;泛型参数通常用单个大写字母,如 T(Type)、K(Key)、V(Value)。变量与函数的命名详见命名规范。
interface MenuItem {}
type RequestResult<T> = Promise<{ data: T }>;
function pluck<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}用常量对象替代部分枚举
对于简单的字面量集合,推荐用 const 对象配合 as const,或直接用字面量联合类型,它们更轻量,且不会生成额外的运行时代码。
// 字面量联合
type Theme = 'light' | 'dark';
// const 对象 + as const
const ROLE = {
Admin: 'admin',
User: 'user'
} as const;
type Role = (typeof ROLE)[keyof typeof ROLE]; // 'admin' | 'user'函数与空值处理
为函数参数标注类型;可选参数用 ?,并优先用默认值替代手动判空。开启 strictNullChecks 后,配合可选链 ?. 与空值合并 ?? 处理可能为空的值。
function greet(name: string, greeting = 'Hello'): string {
return `${greeting}, ${name}`;
}
// 可选链 + 空值合并
const len = user?.name?.length ?? 0;注意 ?? 仅在值为 null 或 undefined 时取右侧,而 || 会把 0、''、false 也视为假值,二者语义不同。
使用 import type 导入类型
仅导入类型时使用 import type,明确区分类型导入与值导入,有助于编译器擦除类型、避免不必要的副作用。
import { ref } from 'vue';
import type { Ref } from 'vue';
import type { User } from './types';