typescript-style
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGoogle TypeScript Style Guide
Google TypeScript 风格指南
Apply Google's TypeScript Style Guide conventions for consistent, maintainable TypeScript code.
遵循Google TypeScript风格指南的规范,编写一致、可维护的TypeScript代码。
Overview
概述
This skill provides guidelines for writing TypeScript code following Google's internal style guide. It covers source file structure, language features, naming conventions, type annotations, and best practices specific to TypeScript development.
本技能提供遵循Google内部风格指南的TypeScript代码编写准则,涵盖源文件结构、语言特性、命名规范、类型注解以及TypeScript开发专属的最佳实践。
Source File Basics
源文件基础
File Encoding
文件编码
Source files must be encoded in UTF-8.
源文件必须采用UTF-8编码。
Whitespace
空白字符
- Use ASCII horizontal space (0x20) as the only whitespace character
- Use special escape sequences (,
\',\",\\,\n,\r, etc.) instead of numeric escapes\t - For non-printable characters, use hex/Unicode escapes with explanatory comments
typescript
// Good: clear unicode character
const units = 'μs';
// Good: escape with comment
const output = '\ufeff' + content; // byte order mark- 仅使用ASCII水平空格(0x20)作为空白字符
- 使用特殊转义序列(,
\',\",\\,\n,\r等)而非数值转义\t - 对于不可打印字符,使用十六进制/Unicode转义并添加解释性注释
typescript
// 推荐:清晰的Unicode字符
const units = 'μs';
// 推荐:带注释的转义字符
const output = '\ufeff' + content; // 字节顺序标记File Structure
文件结构
Files must contain sections in this order (separated by exactly one blank line):
- Copyright information (if present)
- JSDoc (if present)
@fileoverview - Imports
- Implementation
typescript
/**
* @fileoverview Description of file. Lorem ipsum dolor sit amet, consectetur
* adipiscing elit, sed do eiusmod tempor incididunt.
*/
import * as foo from './foo';
import {Bar} from './bar';
export class MyClass { }文件必须按以下顺序包含各部分(各部分之间仅用一个空行分隔):
- 版权信息(若存在)
- JSDoc注释(若存在)
@fileoverview - 导入语句
- 实现代码
typescript
/**
* @fileoverview 文件描述。Lorem ipsum dolor sit amet, consectetur
* adipiscing elit, sed do eiusmod tempor incididunt.
*/
import * as foo from './foo';
import {Bar} from './bar';
export class MyClass { }Imports and Exports
导入与导出
Import Styles
导入风格
Use appropriate import styles:
- Module imports: - for namespacing
import * as foo from '...'; - Named imports: - for frequently used symbols
import {SomeThing} from '...'; - Default imports: - only when required by external code
import SomeThing from '...'; - Side-effect imports: - only for side-effects
import '...';
typescript
// Good: module import for namespace
import * as ng from '@angular/core';
// Good: named import for clear symbols
import {describe, it, expect} from './testing';
// Only when needed
import Button from 'Button';使用合适的导入风格:
- 模块导入:- 用于命名空间
import * as foo from '...'; - 命名导入:- 用于频繁使用的符号
import {SomeThing} from '...'; - 默认导入:- 仅在外部代码要求时使用
import SomeThing from '...'; - 副作用导入:- 仅用于执行副作用的场景
import '...';
typescript
// 推荐:用于命名空间的模块导入
import * as ng from '@angular/core';
// 推荐:用于明确符号的命名导入
import {describe, it, expect} from './testing';
// 仅在必要时使用
import Button from 'Button';Named Exports Only
仅使用命名导出
Always use named exports. Never use default exports.
typescript
// Good: named export
export class Foo { }
export const BAR = 42;typescript
// Bad: default export
export default class Foo { }Why? Default exports provide no canonical name, making refactoring difficult and allowing inconsistent import names.
始终使用命名导出,绝不要使用默认导出。
typescript
// 推荐:命名导出
export class Foo { }
export const BAR = 42;typescript
// 不推荐:默认导出
export default class Foo { }原因:默认导出没有标准名称,会导致重构困难,且允许不一致的导入名称。
Import Paths
导入路径
- Use relative paths () for files within the same project
./foo - Use paths from root for cross-project imports
- Limit parent steps () to maintain clarity
../../../
typescript
import {Symbol1} from 'path/from/root';
import {Symbol2} from '../parent/file';
import {Symbol3} from './sibling';- 同一项目内的文件使用相对路径()
./foo - 跨项目导入使用根路径
- 限制向上层级()以保持路径清晰
../../../
typescript
import {Symbol1} from 'path/from/root';
import {Symbol2} from '../parent/file';
import {Symbol3} from './sibling';Variables and Constants
变量与常量
Use const and let
使用const和let
Always use or . Never use .
constletvartypescript
const foo = otherValue; // Use const by default
let bar = someValue; // Use let when reassigningtypescript
var foo = someValue; // Never use varWhy? and are block-scoped like most languages. is function-scoped and causes bugs.
constletvar始终使用或,绝不要使用。
constletvartypescript
const foo = otherValue; // 默认使用const
let bar = someValue; // 当需要重新赋值时使用lettypescript
var foo = someValue; // 绝不要使用var原因:和像大多数语言一样是块级作用域,而是函数级作用域,容易引发bug。
constletvarOne Variable Per Declaration
单语句单变量
Declare only one variable per statement:
typescript
// Good
let a = 1;
let b = 2;typescript
// Bad
let a = 1, b = 2;每条语句仅声明一个变量:
typescript
// 推荐
let a = 1;
let b = 2;typescript
// 不推荐
let a = 1, b = 2;Arrays and Objects
数组与对象
Array Literals
数组字面量
Do not use the constructor. Use bracket notation:
Arraytypescript
// Good
const a = [2];
const b = [2, 3];
const c = Array.from<number>({length: 5}).fill(0);typescript
// Bad: confusing behavior
const a = new Array(2); // [undefined, undefined]
const b = new Array(2, 3); // [2, 3]不要使用构造函数,使用方括号语法:
Arraytypescript
// 推荐
const a = [2];
const b = [2, 3];
const c = Array.from<number>({length: 5}).fill(0);typescript
// 不推荐:行为易混淆
const a = new Array(2); // [undefined, undefined]
const b = new Array(2, 3); // [2, 3]Object Literals
对象字面量
Do not use the constructor. Use object literals:
Objecttypescript
// Good
const obj = {};
const obj2 = {a: 0, b: 1};typescript
// Bad
const obj = new Object();不要使用构造函数,使用对象字面量:
Objecttypescript
// 推荐
const obj = {};
const obj2 = {a: 0, b: 1};typescript
// 不推荐
const obj = new Object();Spread Syntax
展开语法
Use spread for shallow copying and concatenating:
typescript
// Good: array spread
const foo = [1, 2];
const foo2 = [...foo, 6, 7];
// Good: object spread
const foo = {num: 1};
const foo2 = {...foo, num: 5};Rules:
- Only spread iterables into arrays
- Only spread objects into objects
- Later values override earlier values
使用展开语法进行浅拷贝和拼接:
typescript
// 推荐:数组展开
const foo = [1, 2];
const foo2 = [...foo, 6, 7];
// 推荐:对象展开
const foo = {num: 1};
const foo2 = {...foo, num: 5};规则:
- 仅将可迭代对象展开到数组中
- 仅将对象展开到对象中
- 后续值会覆盖先前值
Destructuring
解构赋值
Use destructuring for unpacking values:
typescript
// Good: array destructuring
const [a, b, c, ...rest] = generateResults();
let [, b, , d] = someArray;
// Good: object destructuring
const {num, str = 'default'} = options;For function parameters, keep destructuring simple (single level, shorthand properties only):
typescript
// Good
function destructured({num, str = 'default'}: Options = {}) { }typescript
// Bad: too deeply nested
function nestedTooDeeply({x: {num, str}}: {x: Options}) { }使用解构赋值提取值:
typescript
// 推荐:数组解构
const [a, b, c, ...rest] = generateResults();
let [, b, , d] = someArray;
// 推荐:对象解构
const {num, str = 'default'} = options;对于函数参数,保持解构简单(仅单层、简写属性):
typescript
// 推荐
function destructured({num, str = 'default'}: Options = {}) { }typescript
// 不推荐:嵌套过深
function nestedTooDeeply({x: {num, str}}: {x: Options}) { }Classes
类
Class Declarations
类声明
Class declarations must not end with semicolons:
typescript
// Good
class Foo {
}typescript
// Bad
class Foo {
};类声明末尾不要加分号:
typescript
// 推荐
class Foo {
}typescript
// 不推荐
class Foo {
};Class Members
类成员
Use readonly
使用readonly
Mark properties never reassigned outside constructor with :
readonlytypescript
class Foo {
private readonly bar = 5;
}对构造函数外永远不会重新赋值的属性标记:
readonlytypescript
class Foo {
private readonly bar = 5;
}Parameter Properties
参数属性
Use parameter properties instead of obvious initializers:
typescript
// Good
class Foo {
constructor(private readonly barService: BarService) {}
}typescript
// Bad: unnecessary boilerplate
class Foo {
private readonly barService: BarService;
constructor(barService: BarService) {
this.barService = barService;
}
}使用参数属性替代冗余的初始化代码:
typescript
// 推荐
class Foo {
constructor(private readonly barService: BarService) {}
}typescript
// 不推荐:不必要的样板代码
class Foo {
private readonly barService: BarService;
constructor(barService: BarService) {
this.barService = barService;
}
}Field Initializers
字段初始化
Initialize fields where declared when possible:
typescript
// Good
class Foo {
private readonly userList: string[] = [];
}typescript
// Bad: unnecessary constructor
class Foo {
private readonly userList: string[];
constructor() {
this.userList = [];
}
}尽可能在声明字段时完成初始化:
typescript
// 推荐
class Foo {
private readonly userList: string[] = [];
}typescript
// 不推荐:不必要的构造函数
class Foo {
private readonly userList: string[];
constructor() {
this.userList = [];
}
}Visibility
可见性
- Limit visibility as much as possible
- Never use modifier except for non-readonly parameter properties
public - TypeScript symbols are public by default
typescript
// Good
class Foo {
bar = new Bar(); // public by default
constructor(public baz: Baz) {} // public modifier allowed
}typescript
// Bad
class Foo {
public bar = new Bar(); // unnecessary
}- 尽可能限制可见性
- 除了非只读参数属性外,绝不要使用修饰符
public - TypeScript符号默认是公共的
typescript
// 推荐
class Foo {
bar = new Bar(); // 默认公共
constructor(public baz: Baz) {} // 允许使用public修饰符
}typescript
// 不推荐
class Foo {
public bar = new Bar(); // 不必要
}No Private Fields (#)
不要使用私有字段(#)
Do not use private fields (). Use TypeScript's modifier instead:
#identprivatetypescript
// Good
class Clazz {
private ident = 1;
}typescript
// Bad
class Clazz {
#ident = 1;
}Why? Private identifiers cause size/performance regressions when downleveled and don't offer benefits over TypeScript's visibility.
不要使用私有字段(),使用TypeScript的修饰符替代:
#identprivatetypescript
// 推荐
class Clazz {
private ident = 1;
}typescript
// 不推荐
class Clazz {
#ident = 1;
}原因:私有标识符在降级编译时会导致体积/性能问题,且相比TypeScript的可见性修饰符没有额外优势。
Functions
函数
Prefer Function Declarations
优先使用函数声明
For named functions, prefer function declarations over arrow functions:
typescript
// Good
function foo() {
return 42;
}typescript
// Bad
const foo = () => 42;对于命名函数,优先使用函数声明而非箭头函数:
typescript
// 推荐
function foo() {
return 42;
}typescript
// 不推荐
const foo = () => 42;Arrow Functions
箭头函数
Use arrow functions for:
- Callbacks and nested functions
- When explicit type annotation required
- When you need to preserve context
this
typescript
// Good: callback
bar(() => { this.doSomething(); });
// Good: nested function with this
class Foo {
method() {
setTimeout(() => {
this.doWork();
}, 100);
}
}在以下场景使用箭头函数:
- 回调函数和嵌套函数
- 需要显式类型注解时
- 需要保留上下文时
this
typescript
// 推荐:回调函数
bar(() => { this.doSomething(); });
// 推荐:保留this的嵌套函数
class Foo {
method() {
setTimeout(() => {
this.doWork();
}, 100);
}
}Arrow Function Bodies
箭头函数体
Use concise bodies when return value is used, block bodies otherwise:
typescript
// Good: return value used
const numbers = [1, 2, 3].map(v => v * 2);
// Good: no return value
myPromise.then(v => {
console.log(v);
});
// Good: explicit void
myPromise.then(v => void console.log(v));当需要返回值时使用简洁体,否则使用块体:
typescript
// 推荐:使用返回值
const numbers = [1, 2, 3].map(v => v * 2);
// 推荐:无返回值
myPromise.then(v => {
console.log(v);
});
// 推荐:显式void
myPromise.then(v => void console.log(v));No Rebinding this
不要重新绑定this
Do not use in function expressions/declarations unless rebinding is needed (which is discouraged):
thistypescript
// Bad
function clickHandler() {
this.textContent = 'Hello';
}
document.body.onclick = clickHandler;typescript
// Good: use arrow function
document.body.onclick = () => {
document.body.textContent = 'hello';
};除非必要(不推荐),否则不要在函数表达式/声明中使用:
thistypescript
// 不推荐
function clickHandler() {
this.textContent = 'Hello';
}
document.body.onclick = clickHandler;typescript
// 推荐:使用箭头函数
document.body.onclick = () => {
document.body.textContent = 'hello';
};Type Annotations
类型注解
Inference
类型推断
Rely on type inference where possible. Do not annotate when the type is obvious:
typescript
// Good: type is obvious
const x = 5;
const y = new Foo();
// Bad: redundant annotation
const x: number = 5;尽可能依赖类型推断,当类型显而易见时不要添加注解:
typescript
// 推荐:类型显而易见
const x = 5;
const y = new Foo();
// 不推荐:冗余注解
const x: number = 5;Return Types
返回类型
Annotate return types on exported functions and public methods:
typescript
// Good
export function foo(): string {
return 'bar';
}对导出函数和公共方法添加返回类型注解:
typescript
// 推荐
export function foo(): string {
return 'bar';
}Type vs Interface
Type与Interface
- Use for object shapes and class contracts
interface - Use for unions, intersections, and mapped types
type - Prefer when either would work
interface
typescript
// Good: interface for object shape
interface User {
name: string;
age: number;
}
// Good: type for union
type Status = 'success' | 'error' | 'pending';- 使用定义对象结构和类契约
interface - 使用定义联合类型、交叉类型和映射类型
type - 当两者都适用时优先使用
interface
typescript
// 推荐:使用interface定义对象结构
interface User {
name: string;
age: number;
}
// 推荐:使用type定义联合类型
type Status = 'success' | 'error' | 'pending';Naming Conventions
命名规范
Identifiers
标识符
Use these naming conventions:
- Classes/Interfaces/Types/Enums:
UpperCamelCase - Functions/Methods/Properties:
lowerCamelCase - Constants:
CONSTANT_CASE - Private properties: prefix with
private - Type parameters: single uppercase letter or
UpperCamelCase
typescript
class MyClass {}
interface UserData {}
type Status = 'active' | 'inactive';
enum Color { RED, GREEN, BLUE }
function doSomething() {}
const userName = 'Alice';
const MAX_COUNT = 100;
class Foo {
private readonly internalState = 5;
}使用以下命名规范:
- 类/接口/类型/枚举:(大驼峰)
UpperCamelCase - 函数/方法/属性:(小驼峰)
lowerCamelCase - 常量:(全大写下划线分隔)
CONSTANT_CASE - 私有属性:前缀使用
private - 类型参数:单个大写字母或
UpperCamelCase
typescript
class MyClass {}
interface UserData {}
type Status = 'active' | 'inactive';
enum Color { RED, GREEN, BLUE }
function doSomething() {}
const userName = 'Alice';
const MAX_COUNT = 100;
class Foo {
private readonly internalState = 5;
}File Names
文件名
- Use lowercase with dashes:
file-name.ts - Match exported symbol when exporting single symbol
- Use for declaration files
.d.ts
- 使用小写加短横线:
file-name.ts - 当导出单个符号时,文件名与导出符号匹配
- 声明文件使用后缀
.d.ts
String Literals
字符串字面量
Use Single Quotes
使用单引号
Use single quotes for ordinary strings:
typescript
// Good
const message = 'Hello world';typescript
// Bad
const message = "Hello world";普通字符串使用单引号:
typescript
// 推荐
const message = 'Hello world';typescript
// 不推荐
const message = "Hello world";Template Literals
模板字面量
Use template literals for:
- String interpolation
- Multi-line strings
- Complex concatenation
typescript
// Good
const greeting = `Hello ${name}`;
const multiline = `Line 1
Line 2`;在以下场景使用模板字面量:
- 字符串插值
- 多行字符串
- 复杂拼接
typescript
// 推荐
const greeting = `Hello ${name}`;
const multiline = `Line 1
Line 2`;Type Coercion
类型转换
Explicit Coercion
显式转换
Use , , for type coercion:
String()Boolean()Number()typescript
// Good
const bool = Boolean(value);
const str = String(num);
const num = Number(str);使用、、进行类型转换:
String()Boolean()Number()typescript
// 推荐
const bool = Boolean(value);
const str = String(num);
const num = Number(str);No Implicit Enum Coercion
不要隐式转换枚举
Never convert enums to booleans implicitly. Compare explicitly:
typescript
enum SupportLevel { NONE, BASIC, ADVANCED }
// Bad
if (level) { }
// Good
if (level !== SupportLevel.NONE) { }永远不要隐式将枚举转换为布尔值,显式进行比较:
typescript
enum SupportLevel { NONE, BASIC, ADVANCED }
// 不推荐
if (level) { }
// 推荐
if (level !== SupportLevel.NONE) { }Quick Reference
快速参考
DO
推荐做法
- Use and
const, neverletvar - Use named exports only
- Use for immutable properties
readonly - Use parameter properties
- Initialize fields where declared
- Use single quotes for strings
- Use template literals for interpolation
- Annotate return types on public functions
- Prefer over
interfacefor objectstype
- 使用和
const,绝不要使用letvar - 仅使用命名导出
- 对不可变属性使用
readonly - 使用参数属性
- 在声明字段时完成初始化
- 字符串使用单引号
- 插值使用模板字面量
- 对公共函数添加返回类型注解
- 定义对象时优先使用
interface
DON'T
不推荐做法
- Use default exports
- Use for variables
var - Use or
Array()constructorsObject() - Use private fields ()
# - Rebind unnecessarily
this - Use function expressions (use arrows instead)
- Mix quoted and unquoted object keys
- Coerce enums to booleans
- 使用默认导出
- 使用声明变量
var - 使用或
Array()构造函数Object() - 使用私有字段()
# - 不必要地重新绑定
this - 使用函数表达式(改用箭头函数)
- 混合使用带引号和不带引号的对象键
- 隐式转换枚举为布尔值
Additional Resources
额外资源
Reference Files
参考文档
For detailed specifications:
- - Detailed coverage of TypeScript language features
references/language-features.md - - Type annotations, generics, utility types
references/type-system.md - - Complete naming rules and examples
references/naming-conventions.md
如需详细规范,请查看:
- - TypeScript语言特性的详细说明
references/language-features.md - - 类型注解、泛型、工具类型
references/type-system.md - - 完整的命名规则与示例
references/naming-conventions.md
Example Files
示例文件
Working examples in :
examples/- - Well-structured class with best practices
examples/class-example.ts - - Function declarations and arrow functions
examples/function-example.ts - - Type definitions and interfaces
examples/types-example.ts
examples/- - 结构规范的类实现最佳实践
examples/class-example.ts - - 函数声明与箭头函数示例
examples/function-example.ts - - 类型定义与接口示例
examples/types-example.ts