TypeScript 与 npm 实用指南
1. TypeScript 基础特性
1.1 readonly 修饰符
在 ES6 中, const 关键字可用于变量,但不能用于类或接口的属性。例如,以下代码会产生编译错误:
class Person {
const name: = "Mary"; // compiler error
}
const p = new Person(); // no errors
而 TypeScript 引入了 readonly 关键字,可用于类属性。 readonly 属性只能在声明时或类的构造函数中初始化。示例如下:
class Person {
readonly name = "Mary"; // no errors
changeName() {
this.name = "John"; // compiler error
}
}
若要创建不可变对象,可将 readonly 应用于对象属性。不过,若直接将 readonly 用于对象属性,只能防止对象引用的重新赋值,不能防止修改对象内部属性。示例如下:
class Person {
readonly bestFriend: { name: string } = {name: "Mary"};
changeFriend() {
this.bestFriend = { name: "John" }; // compiler error
}
changeFriendName() {
this.bestFriend.name = "John"; // no errors
}
}
若要禁止修改对象内部属性,需为对象的每个属性添加 readonly 修饰符:
class Person {
readonly bestFriend: { readonly name: string } = {name: "Mary"};
changeFriend() {
this.bestFriend = { name: "John" }; // compiler error
}
changeFriendName(newName: string) {
this.bestFriend.name = "John"; // compiler error
}
}
当对象有多个属性时,为每个属性添加 readonly 修饰符较为繁琐,可使用只读映射类型。示例如下:
type Friend = Readonly<{ name: string, lastName: string }>;
class Person {
bestFriend: Friend = {name: "Mary", lastName: "Smith"};
changeFriend() {
this.bestFriend = { name: "John" }; // compiler error
}
changeFriendName() {
this.bestFriend.name = "John"; // compiler error
this.bestFriend.lastName = "Lou"; // compiler error
}
}
1.2 装饰器
装饰器是 TypeScript 中的特殊函数,以 @ 符号开头,用于为类、属性、方法或参数添加元数据,增强其功能。在 TypeScript 中使用装饰器,需在 tsconfig.json 文件中开启实验特性:
"experimentalDecorators": true
以下是一个简单装饰器的示例,它能打印所附着类的信息:
function UIComponent (html: string) {
console.log(`The decorator received ${html} \n`);
return function(target) {
console.log(`Creating a UI component from \n ${target} ` );
}
}
@UIComponent('<h1>Hello Shopper!</h1>')
class Shopper {
constructor(private name: string) {}
}
若将上述代码编译为 ES5 语法并运行,控制台输出如下:
The decorator received <h1>Hello Shopper!</h1>
Creating a UI component from
function Shopper(name) {
this.name = name;
}
若编译为 ES6 语法,输出如下:
The decorator received <h1>Hello Shopper!</h1>
Creating a UI component from
class Shopper {
constructor(name) {
this.name = name;
}
}
在 Angular 中,可使用 @Component() 装饰器将 TypeScript 类转换为 Angular 组件,使用 @Input() 装饰器使类变量能接收父组件的值。示例如下:
import { Component, Input } from '@angular/core';
@Component({
selector: 'order-processor',
template: `
Buying {{quantity}} shares
`
})
export class OrderComponent {
@Input() quantity: number;
}
1.3 联合类型
在 TypeScript 中,可基于两个或多个现有类型声明新类型。例如,可声明一个变量,它能接受字符串或数字值:
let padding: string | number;
以下是一个为字符串添加左填充的函数示例:
function padLeft(value: string, padding: any ) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
调用示例如下:
console.log( padLeft("Hello world", 4)); // returns " Hello world"
console.log( padLeft("Hello world", "John says ")); // returns "John says Hello world"
console.log( padLeft("Hello world", true)); // runtime error
若将 padding 的类型改为字符串或数字的联合类型,编译器会在传入非字符串或数字类型时报错,且无需抛出异常:
function padLeft(value: string, padding: string | number ) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
}
调用示例如下:
console.log( padLeft("Hello world", true)); // compilation error
使用联合类型的好处是,IDE 的自动补全功能会提示允许的参数类型,减少错误发生。
1.4 使用类型定义文件
类型定义文件用于描述 JavaScript 库的 API 所提供的类型。TypeScript 社区最初创建了 DefinitelyTyped 仓库,2016 年微软在 npmjs.org 上创建了 @types 组织,包含 5000 多个各种 JavaScript 库的类型定义文件。
类型定义文件的文件名后缀为 .d.ts ,可使用 npm 安装。例如,安装 Lodash 的类型定义文件:
npm i @types/lodash --save-dev
安装 Angular 时,运行 npm install 后,Angular 模块的定义文件会位于 node_modules/@angular 文件夹的子文件夹中,无需单独安装。类型定义文件能让 TypeScript 编译器确保代码在调用 API 时使用正确的类型,IDE 也能提供上下文敏感帮助。
1.5 控制代码风格的 TSLint
TSLint 可确保 TypeScript 代码符合指定的编码风格。可使用以下命令全局安装 TSLint:
npm install tslint -g
在项目目录中安装 TSLint 模块:
npm install tslint
代码规则在 tslint.json 配置文件中指定,可通过运行 tslint init 生成:
{
"defaultSeverity": "error",
"extends": [
"tslint: recommended"
],
"jsRules": {},
"rules": {},
"rulesDirectory": []
}
可根据需要使用自定义规则,核心 TSLint 规则文档可参考 http://mng.bz/xx6B 。部分 IDE 支持 TSLint 自动检查代码风格。
2. 使用 npm 包管理器
2.1 Node.js 与 npm 简介
Node.js 不仅是框架或库,还是 JavaScript 运行时环境。可使用 Node 运行 npm 等工具,也可使用 npm 脚本自动化构建、测试和部署 Angular 应用。
首先,从 https://nodejs.org 下载并安装当前版本的 Node.js。安装完成后,在终端或命令窗口输入以下命令检查版本:
node --version
Node 自带 npm 包管理器,可从 www.npmjs.com 上的 npm 注册表安装 Angular 及其他包。
2.2 npm 安装包的操作
使用 npm install (或简写为 npm i )命令安装 JavaScript 库。例如,在任意目录下安装 TypeScript 编译器:
npm i typescript
安装完成后,会在当前目录下创建 node_modules 子目录,用于存放安装的包。若要全局安装包,可添加 -g 选项:
npm i typescript -g
若要安装特定版本的包,可在包名后添加 @ 符号和版本号。例如,全局安装 TypeScript 2.9.0:
npm i typescript@2.9.0 -g
npm install 命令的所有可用选项可参考 https://docs.npmjs.com/cli/install 。
有时可能需要同时在本地和全局安装同一包。例如,本地安装 TypeScript 2.7,全局安装 TypeScript 2.9。运行全局版本的编译器,在终端输入 tsc 命令;运行本地安装的编译器,可在项目目录下使用以下命令:
node_modules/.bin/tsc
2.3 在 package.json 中指定项目依赖
创建新的基于 Node 的项目时,可使用以下步骤创建 package.json 文件:
1. 创建新目录,如 my-node-project 。
2. 打开终端或命令窗口,将当前工作目录切换到新目录。
3. 运行 npm init -y 命令,创建 package.json 配置文件的初始版本。
$ npm init -y
Wrote to /Users/username/my-node-project/package.json:
{
"name": "my-node-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
由于不打算将项目发布到 npm 注册表,可移除除 name 、 description 和 scripts 之外的属性,并添加 "private": true 属性,防止意外发布。修改后的 package.json 文件如下:
{
"name": "my-node-project",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}
scripts 配置可指定命令别名,可在命令窗口运行。默认创建的 test 别名,可使用 npm test 命令运行。也可创建自定义命令别名,运行时需添加 run 关键字。例如:
"scripts": {
"deploy": "copyfiles -f dist/** ../server/build/public",
}
运行自定义命令:
npm run deploy
若使用 npm init 命令生成 package.json 文件,会缺少 dependencies 和 devDependencies 两个重要部分。使用 Angular CLI 生成项目时,会自动创建包含正确内容的 package.json 文件。
2.4 项目依赖管理总结
在管理项目依赖时, package.json 文件起着至关重要的作用。下面通过表格总结 package.json 文件中各部分的作用:
| 部分 | 作用 |
| — | — |
| name | 项目的名称,用于标识项目 |
| description | 项目的简要描述 |
| private | 设置为 true 可防止项目意外发布到 npm 注册表 |
| scripts | 定义命令别名,方便在命令行中运行各种脚本,如测试、部署等 |
| dependencies | 项目运行时所需的依赖包 |
| devDependencies | 项目开发过程中所需的依赖包,如测试工具、构建工具等 |
2.5 npm 安装流程总结
为了更清晰地展示使用 npm 安装包的流程,下面给出 mermaid 格式的流程图:
graph LR
A[开始] --> B[确定安装方式]
B --> |本地安装| C[npm i 包名]
B --> |全局安装| D[npm i 包名 -g]
B --> |特定版本安装| E[npm i 包名@版本号 -g]
C --> F[安装到 node_modules 目录]
D --> G[安装到全局 lib/node_modules 目录]
E --> G
F --> H[完成本地安装]
G --> I[完成全局安装]
H --> J[结束]
I --> J
3. TypeScript 与 npm 结合应用案例
3.1 创建 Angular 项目示例
下面以创建一个简单的 Angular 项目为例,展示 TypeScript 和 npm 的结合使用。
步骤:
- 安装 Angular CLI :使用
npm全局安装 Angular CLI。
npm i @angular/cli -g
- 创建新项目 :使用 Angular CLI 创建一个新的 Angular 项目。
ng new my-angular-project
cd my-angular-project
- 查看
package.json文件 :项目创建完成后,查看package.json文件,其中包含了项目的依赖信息。
{
"name": "my-angular-project",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "~14.0.0",
"@angular/common": "~14.0.0",
"@angular/compiler": "~14.0.0",
"@angular/core": "~14.0.0",
"@angular/forms": "~14.0.0",
"@angular/platform-browser": "~14.0.0",
"@angular/platform-browser-dynamic": "~14.0.0",
"@angular/router": "~14.0.0",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~14.0.0",
"@angular/cli": "~14.0.0",
"@angular/compiler-cli": "~14.0.0",
"@types/jasmine": "~4.0.0",
"jasmine-core": "~4.1.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.7.2"
}
}
- 运行项目 :使用
npm脚本启动项目。
npm start
3.2 代码风格检查示例
在 Angular 项目中使用 TSLint 进行代码风格检查。
步骤:
- 安装 TSLint :在项目目录中安装 TSLint。
npm install tslint
- 初始化 TSLint 配置文件 :运行
tslint init生成tslint.json文件。
tslint init
- 配置规则 :根据项目需求修改
tslint.json文件中的规则。
{
"defaultSeverity": "error",
"extends": [
"tslint: recommended"
],
"jsRules": {},
"rules": {
"align": {
"options": ["parameters", "statements"],
"severity": "error"
},
"class-name": true,
"comment-format": {
"options": ["check-space"],
"severity": "error"
},
"indent": {
"options": ["spaces", 4],
"severity": "error"
},
"no-console": {
"options": ["log", "error", "debug", "info", "time", "timeEnd", "trace"],
"severity": "error"
},
"no-duplicate-variable": true,
"no-eval": true,
"no-internal-module": true,
"no-namespace": true,
"no-unused-variable": true,
"quotemark": {
"options": ["single"],
"severity": "error"
},
"semicolon": {
"options": ["always"],
"severity": "error"
},
"trailing-comma": {
"options": ["always"],
"severity": "error"
},
"whitespace": {
"options": ["check-branch", "check-decl", "check-operator", "check-separator", "check-type"],
"severity": "error"
}
},
"rulesDirectory": []
}
- 运行代码检查 :在命令行中运行 TSLint 检查代码。
npx tslint src/**/*.ts
4. 总结
本文介绍了 TypeScript 的基础特性,包括 readonly 修饰符、装饰器、联合类型、类型定义文件和 TSLint 代码风格检查,同时详细讲解了 npm 包管理器的使用,包括安装包、管理项目依赖等。通过具体的操作步骤和代码示例,展示了如何将 TypeScript 和 npm 结合应用于实际项目中。希望这些内容能帮助你更好地掌握 TypeScript 和 npm 的使用,提高开发效率和代码质量。
在实际开发中,可根据项目需求灵活运用这些技术,不断优化项目的开发流程和代码结构。例如,合理使用 readonly 修饰符创建不可变对象,提高代码的安全性;使用装饰器为类、属性等添加额外的功能;利用联合类型增强代码的类型安全性;通过 npm 管理项目依赖,确保项目的稳定性和可维护性。同时,要养成良好的代码风格习惯,使用 TSLint 等工具进行代码检查,提高代码的可读性和规范性。
超级会员免费看
666

被折叠的 条评论
为什么被折叠?



