本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
遵循 TypeScript 最佳实践
TypeScript 是一种扩展功能的语言 JavaScript。它是一种强类型化且面向对象的语言。您可以使用 TypeScript 来指定代码中传递的数据类型,并且能够在类型不匹配时报告错误。本部分提供 TypeScript 最佳实践。
描述您的数据
您可以使用 TypeScript 来描述代码中对象和函数的形状。使用any
类型等同于选择不检查变量的类型。我们建议您避免在代码any
中使用。以下是示例。
type Result = "success" | "failure" function verifyResult(result: Result) { if (result === "success") { console.log("Passed"); } else { console.log("Failed") } }
使用枚举
您可以使用枚举来定义一组命名常量并定义可在代码库中重用的标准。我们建议您在全局级别导出一次枚举,然后让其他类导入和使用这些枚举。假设你想创建一组可能的操作来捕获代码库中的事件。 TypeScript 提供基于数字和字符串的枚举。以下示例使用枚举。
enum EventType { Create, Delete, Update } class InfraEvent { constructor(event: EventType) { if (event === EventType.Create) { // Call for other function console.log(`Event Captured :${event}`); } } } let eventSource: EventType = EventType.Create; const eventExample = new InfraEvent(eventSource)
使用接口
接口是类的合约。如果您创建合同,则您的用户必须遵守合同。在以下示例中,接口用于标准化props
并确保调用者在使用该类时提供预期的参数。
import { Stack, App } from "aws-cdk-lib"; import { Construct } from "constructs"; interface BucketProps { name: string; region: string; encryption: boolean; } class S3Bucket extends Stack { constructor(scope: Construct, props: BucketProps) { super(scope); console.log(props.name); } } const app = App(); const myS3Bucket = new S3Bucket(app, { name: "my-bucket", region: "us-east-1", encryption: false })
某些属性只能在首次创建对象时修改。您可以通过在属性的名称readonly
之前指定此项,如下例所示。
interface Position { readonly latitude: number; readonly longitute: number; }
扩展接口
扩展接口可以减少重复,因为您不必在接口之间复制属性。此外,代码的读者可以轻松理解应用程序中的关系。
interface BaseInterface{ name: string; } interface EncryptedVolume extends BaseInterface{ keyName: string; } interface UnencryptedVolume extends BaseInterface { tags: string[]; }
避免空的接口
我们建议您避免使用空接口,因为它们会带来潜在风险。在以下示例中,有一个名为的空接口BucketProps
。myS3Bucket1
和myS3Bucket2
对象均有效,但它们遵循不同的标准,因为接口不强制执行任何合约。以下代码将编译并打印这些属性,但这会在您的应用程序中引入不一致性。
interface BucketProps {} class S3Bucket implements BucketProps { constructor(props: BucketProps){ console.log(props); } } const myS3Bucket1 = new S3Bucket({ name: "my-bucket", region: "us-east-1", encryption: false, }); const myS3Bucket2 = new S3Bucket({ name: "my-bucket", });
使用工厂
在抽象工厂模式中,接口负责创建相关对象的工厂,而无需明确指定其类。例如,您可以创建一个 Lambda 工厂来创建 Lambda 函数。您不是在构造中创建新的 Lambda 函数,而是将创建过程委托给工厂。有关此设计模式的更多信息,请参阅 Refactoring.Guru 文档 TypeScript中的抽象工
对属性使用解构
ECMAScript 6 (ES6) 中引入的解构 JavaScript 功能使您能够从数组或对象中提取多条数据并将它们分配给它们自己的变量。
const object = { objname: "obj", scope: "this", }; const oName = object.objname; const oScop = object.scope; const { objname, scope } = object;
定义标准命名惯例
强制执行命名约定可以保持代码库的一致性,并在考虑如何命名变量时减少开销。我们建议执行下列操作:
使用 CamelCase 作为变量和函数名称。
PascalCase 用于类名和接口名。
使用 CamelCase 作为接口成员。
PascalCase 用于类型名称和枚举名称。
使用 camelCase 命名文件(例如,
ebsVolumes.tsx
或storage.tsb
)
不要使用 var 关键字
该let
语句用于在中声明局部变量 TypeScript。它与var
关键字类似,但与var
关键字相比,它在范围上有一些限制。在的块中声明的变let
量只能在该块中使用。该var
关键字具有全局范围,这意味着它可用并且只能在该函数内访问。您可以重新声明和更新var
变量。最佳做法是避免使用var
关键字。
考虑使用 ESLint 和 Prettier
ESLint 静态分析您的代码以快速发现问题。您可以使用 ESLint 创建一系列断言(称为 lint 规则),这些断言定义代码的外观或行为。ESLint 还提供自动修复建议,可帮助您改进代码。最后,你可以使用 ESLint 加载来自共享插件的 lint 规则。
Prettier 是众所周知的代码格式化程序,支持各种不同的编程语言。你可以使用 Prettier 来设置你的代码风格,这样你就可以避免手动格式化你的代码。安装后,您可以更新package.json
文件并运行npm run format
和npm run lint
命令。
以下示例展示了如何为您的 AWS CDK 项目启用 ESLint 和 Prettier 格式化程序。
"scripts": { "build": "tsc", "watch": "tsc -w", "test": "jest", "cdk": "cdk", "lint": "eslint --ext .js,.ts .", "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\"" }
使用访问修饰符
中的私有修饰符将可见性 TypeScript 限制为仅限同一个类。将私有修饰符添加到属性或方法时,可以在同一个类中访问该属性或方法。
public 修饰符允许从所有位置访问类属性和方法。如果您没有为属性和方法指定任何访问修饰符,则默认情况下它们将使用公共修饰符。
protected 修饰符允许在同一个类和子类中访问一个类的属性和方法。当您希望在 AWS CDK 应用程序中创建子类时,请使用受保护的修饰符。