44、TypeScript 与 npm 实用指南

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 的结合使用。

步骤:
  1. 安装 Angular CLI :使用 npm 全局安装 Angular CLI。
npm i @angular/cli -g
  1. 创建新项目 :使用 Angular CLI 创建一个新的 Angular 项目。
ng new my-angular-project
cd my-angular-project
  1. 查看 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"
  }
}
  1. 运行项目 :使用 npm 脚本启动项目。
npm start

3.2 代码风格检查示例

在 Angular 项目中使用 TSLint 进行代码风格检查。

步骤:
  1. 安装 TSLint :在项目目录中安装 TSLint。
npm install tslint
  1. 初始化 TSLint 配置文件 :运行 tslint init 生成 tslint.json 文件。
tslint init
  1. 配置规则 :根据项目需求修改 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": []
}
  1. 运行代码检查 :在命令行中运行 TSLint 检查代码。
npx tslint src/**/*.ts

4. 总结

本文介绍了 TypeScript 的基础特性,包括 readonly 修饰符、装饰器、联合类型、类型定义文件和 TSLint 代码风格检查,同时详细讲解了 npm 包管理器的使用,包括安装包、管理项目依赖等。通过具体的操作步骤和代码示例,展示了如何将 TypeScript 和 npm 结合应用于实际项目中。希望这些内容能帮助你更好地掌握 TypeScript 和 npm 的使用,提高开发效率和代码质量。

在实际开发中,可根据项目需求灵活运用这些技术,不断优化项目的开发流程和代码结构。例如,合理使用 readonly 修饰符创建不可变对象,提高代码的安全性;使用装饰器为类、属性等添加额外的功能;利用联合类型增强代码的类型安全性;通过 npm 管理项目依赖,确保项目的稳定性和可维护性。同时,要养成良好的代码风格习惯,使用 TSLint 等工具进行代码检查,提高代码的可读性和规范性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值