学习:TypeScript (1)

TypeScript 简介

TypeScript 是由微软开发的一种编程语言,它是 JavaScript 的超集(TypeScript⊇JavaScript),于 2012 年首次发布。TypeScript 添加了静态类型和其他特性到 JavaScript 中,使得大型应用程序的开发更加容易和维护性更强。

TypeScript 的主要特点:

  1. 静态类型系统 - 允许在编码阶段捕获类型错误
  2. 面向对象编程 - 支持类、接口、继承等特性
  3. 现代 JavaScript 特性 - 支持最新的 ECMAScript 标准
  4. 更好的 IDE 支持 - 提供更精准的代码补全、重构和导航
  5. 编译时错误检查 - 在代码运行前发现潜在问题

JavaScript 与 TypeScript 的主要区别

让我通过一个表格和代码示例来展示它们的主要区别:

特性 JavaScript TypeScript
类型系统 动态类型 静态类型(可选)
编译 解释执行 编译为 JavaScript
错误检测 运行时 编译时 + 运行时
代码补全 基础 更精准
学习曲线 较低 较陡峭

代码示例对比

JavaScript 示例:
javascript 复制代码
function calculateTotal(price, quantity) {
    return price * quantity;
}

// 调用函数
let total = calculateTotal(10, 5);
console.log(total); // 输出: 50

// 可能的错误 - JavaScript 不会报错
let wrongTotal = calculateTotal("10", "5"); 
console.log(wrongTotal); // 输出: "50" (字符串拼接)
TypeScript 示例:
TypeScript 复制代码
function calculateTotal(price: number, quantity: number): number {
    return price * quantity;
}

// 正确调用
let total: number = calculateTotal(10, 5);
console.log(total); // 输出: 50

// 错误调用 - TypeScript 会在编译时报错
// let wrongTotal = calculateTotal("10", "5"); 
// 错误: 类型"string"的参数不能赋给类型"number"的参数

主要差异详解

1.类型注解

  • JavaScript: 不需要显式声明类型
  • TypeScript: 可以使用类型注解明确变量、函数参数和返回值的类型

2.接口定义

  • TypeScript 允许定义接口,强制对象结构符合特定形状
TypeScript 复制代码
// TypeScript 接口示例
interface User {
    id: number;
    name: string;
    email?: string; // 可选属性
}

function processUser(user: User) {
    console.log(`Processing user: ${user.name}`);
}

// JavaScript 中没有这种强制结构的方式

3.枚举类型

  • TypeScript 提供枚举,JavaScript 没有原生枚举支持
TypeScript 复制代码
// TypeScript 枚举示例
enum Color {
    Red,
    Green,
    Blue
}

let favoriteColor: Color = Color.Blue;

4.泛型

  • TypeScript 支持泛型,使代码更加灵活和可重用
TypeScript 复制代码
// TypeScript 泛型示例
function identity<T>(arg: T): T {
    return arg;
}

let output = identity<string>("myString");

5.访问修饰符

  • TypeScript 支持 public、private 和 protected 访问修饰符
TypeScript 复制代码
class Person {
    private name: string;
    public age: number;
    
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    
    public getInfo(): string {
        return `${this.name} is ${this.age} years old`;
    }
}

为什么要学习 TypeScript?

  1. 减少运行时错误:通过类型检查在开发阶段捕获更多错误
  2. 提高代码质量:类型系统使代码更加自文档化
  3. 更好的团队协作:明确的类型定义使团队成员更容易理解代码
  4. 强大的工具支持:提供更精确的自动补全、重构和导航功能
  5. 现代 JavaScript 特性:支持最新的 ECMAScript 特性,并可编译到旧版本

TypeScript 安装

在安装 TypeScript 之前,请确保您的系统已安装:

  • Node.js(建议版本 14 或更高)
  • npm(通常随 Node.js 一起安装)

方法一:全局安装(推荐初学者)

全局安装后,可以在任何项目中使用 TypeScript:

TypeScript 复制代码
npm install -g typescript

安装完成后,检查版本:

TypeScript 复制代码
tsc -v

方法二:项目级安装

在特定项目中安装 TypeScript:

TypeScript 复制代码
# 初始化项目(如果还没有 package.json)
npm init -y

# 安装 TypeScript 作为开发依赖
npm install --save-dev typescript

使用项目级安装的 TypeScript:

TypeScript 复制代码
# npx 命令会使用项目本地安装的版本
npx tsc -v

验证安装

创建一个简单的 TypeScript 文件来测试安装:

1.创建一个名为 test.ts 的文件:

TypeScript 复制代码
function greet(name: string): string {
    return `Hello, ${name}!`;
}

console.log(greet("TypeScript"));

2.编译该文件:

复制代码
tsc test.ts

3.运行生成的 JavaScript 文件:

复制代码
node test.js

输出: Hello, TypeScript!

配置 TypeScript 项目

对于正式项目,建议创建一个 TypeScript 配置文件:

1.生成 tsconfig.json 文件:

复制代码
tsc --init

2.常用配置选项(编辑生成的 tsconfig.json ):

TypeScript 复制代码
{
  "compilerOptions": {
    "target": "ES2020",          // 编译目标 JavaScript 版本
    "module": "commonjs",        // 使用的模块系统
    "outDir": "./dist",          // 输出目录
    "rootDir": "./src",          // 源代码目录
    "strict": true,              // 启用所有严格类型检查选项
    "esModuleInterop": true,     // 启用更好的 CommonJS 模块互操作性
    "skipLibCheck": true,        // 跳过库文件的类型检查
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],       // 包含的文件
  "exclude": ["node_modules"]    // 排除的目录
}

默认的

TypeScript 复制代码
{
  // Visit https://aka.ms/tsconfig to read more about this file
  "compilerOptions": {
    // File Layout
    // "rootDir": "./src",
    // "outDir": "./dist",

    // Environment Settings
    // See also https://aka.ms/tsconfig/module
    "module": "nodenext",
    "target": "esnext",
    "types": [],
    // For nodejs:
    // "lib": ["esnext"],
    // "types": ["node"],
    // and npm install -D @types/node

    // Other Outputs
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true,

    // Stricter Typechecking Options
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,

    // Style Options
    // "noImplicitReturns": true,
    // "noImplicitOverride": true,
    // "noUnusedLocals": true,
    // "noUnusedParameters": true,
    // "noFallthroughCasesInSwitch": true,
    // "noPropertyAccessFromIndexSignature": true,

    // Recommended Options
    "strict": true,
    "jsx": "react-jsx",
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "noUncheckedSideEffectImports": true,
    "moduleDetection": "force",
    "skipLibCheck": true,
  }
}

常用编译命令

复制代码
# 编译单个文件
tsc filename.ts

# 监视文件变化,自动编译
tsc filename.ts --watch

# 使用配置文件编译项目
tsc

# 监视整个项目
tsc --watch

安装额外工具

安装 TypeScript 声明文件

许多 JavaScript 库有类型定义,可以安装以获得更好的类型支持:

复制代码
# 安装 Node.js 类型定义
npm install --save-dev @types/node

# 安装特定库的类型定义
npm install --save-dev @types/jquery

安装 ts-node(直接运行 TypeScript 文件)

复制代码
npm install -g ts-node

使用 ts-node 运行 TypeScript 文件而无需先编译:

复制代码
ts-node filename.ts

在代码编辑器中设置 TypeScript

Visual Studio Code

VS Code 对 TypeScript 有内置支持,但您可以:

  1. 安装 "TypeScript Importer" 扩展自动导入模块
  2. 安装 "TypeScript Hero" 更好地组织导入

其他编辑器

  • WebStorm:内置 TypeScript 支持
  • Sublime Text:安装 "TypeScript" 插件
  • Atom:安装 "atom-typescript" 包

TypeScript 特性

TypeScript 作为 JavaScript 的超集,添加了许多强大的类型系统和编程特性。

1. 静态类型系统

TypeScript 最显著的特性是静态类型系统,它允许在编译时检测类型错误,而不是等到运行时才发现。

基本类型注解

TypeScript 复制代码
// 基本类型
let isDone: boolean = false;
let decimal: number = 6;
let color: string = "blue";
let list: number[] = [1, 2, 3];
let x: [string, number] = ["hello", 10]; // 元组

// 输出基本类型
console.log("基本类型输出:");
console.log("isDone:", isDone);
console.log("decimal:", decimal);
console.log("color:", color);
console.log("list:", list);
console.log("x:", x);

// 枚举
enum Color {
  Red,
  Green,
  Blue,
}
let c: Color = Color.Green;

// 输出枚举
console.log("\n枚举输出:");
console.log("Color.Green:", c);

// any 类型 - 可以是任意类型
let notSure: any = 4;
notSure = "maybe a string";

// 输出any类型
console.log("\nany类型输出:");
console.log("notSure:", notSure);


// void 类型 - 通常用于函数返回值
function warnUser(): void {
  console.log("This is a warning message");
}

2. 接口 (Interfaces)

接口定义了对象的结构,确保对象符合特定的形状。

TypeScript 复制代码
interface Person {
    name: string;
    age: number;
    // 可选属性
    nickname?: string;
    // 只读属性
    readonly id: number;
}

function greetPerson(person: Person): string {
    return `Hello, ${person.name}!`;
}

// 正确使用
let user: Person = { id: 1, name: "Alice", age: 30 };
greetPerson(user);

// 错误 - 缺少必需属性
// let invalidUser: Person = { name: "Bob" };

3. 类 (Classes)

TypeScript 提供了完整的基于类的面向对象编程支持。

TypeScript 复制代码
class Animal {
  // 私有属性
  private name: string;

  // 受保护的属性
  protected species: string;

  // 公共属性
  public age: number;

  constructor(name: string, species: string, age: number) {
    this.name = name;
    this.species = species;
    this.age = age;
  }

  // 公共方法
  public move(distanceInMeters: number): void {
    console.log(`${this.name} moved ${distanceInMeters}m.`);
  }

  // 私有方法
  private sleep(): void {
    console.log(`${this.name} is sleeping.`);
  }
}

// 继承
class Dog extends Animal {
  constructor(name: string, age: number) {
    super(name, "Canine", age);
  }

  public bark(): void {
    console.log("Woof! Woof!");
  }
}

// 创建实例并调用方法
const myDog = new Dog("Buddy", 3);
console.log(`Dog's name: ${myDog["name"]}`); // 注意:name是私有属性,这里只是为了演示
console.log(`Dog's age: ${myDog.age}`);
myDog.bark();
myDog.move(10);

4. 泛型 (Generics)

泛型使代码更加灵活和可重用,同时保持类型安全。

TypeScript 复制代码
// 泛型函数
function identity<T>(arg: T): T {
  return arg;
}

let output1 = identity<string>("myString");
let output2 = identity<number>(100);

// 泛型接口
interface GenericIdentityFn<T> {
  (arg: T): T;
}

let myIdentity: GenericIdentityFn<number> = identity;

// 泛型类
class GenericNumber<T> {
  zeroValue: T = {} as T; // 添加初始化表达式
  add: (x: T, y: T) => T = (x, y) => x; // 添加初始化表达式
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
  return x + y;
};

// 添加输出语句
console.log("泛型函数输出:");
console.log("output1:", output1);
console.log("output2:", output2);

console.log("泛型接口输出:");
console.log("myIdentity(5):", myIdentity(5));

console.log("泛型类输出:");
console.log("zeroValue:", myGenericNumber.zeroValue);
console.log("add(10, 20):", myGenericNumber.add(10, 20));

// 使用字符串类型的泛型类
let stringGeneric = new GenericNumber<string>();
stringGeneric.zeroValue = "";
stringGeneric.add = function (x, y) {
  return x + y;
};

console.log("字符串类型的泛型类:");
console.log("zeroValue:", stringGeneric.zeroValue);
console.log(
  'add("Hello, ", "World!"):',
  stringGeneric.add("Hello, ", "World!")
);

5. 联合类型与交叉类型

联合类型 (Union Types)

联合类型表示一个值可以是几种类型之一。

TypeScript 复制代码
// 联合类型
function displayValue(value: string | number): void {
  if (typeof value === "string") {
    console.log(`String value: ${value.toUpperCase()}`);
  } else {
    console.log(`Number value: ${value.toFixed(2)}`);
  }
}

console.log("=== 联合类型示例 ===");
console.log("处理字符串值:");
displayValue("hello");
console.log("处理数字值:");
displayValue(42.5);

// 更多示例
console.log("=== 更多联合类型示例 ===");
const stringValue: string | number = "TypeScript";
console.log("当前值为字符串:", stringValue);

const numberValue: string | number = 2023;
console.log("当前值为数字:", numberValue);

// 联合类型函数
function processValue(input: string | number): string {
  return typeof input === "string"
    ? `处理字符串: ${input.length}个字符`
    : `处理数字: ${input * 2}`;
}

console.log("=== 联合类型函数示例 ===");
console.log(processValue("联合类型"));
console.log(processValue(50));

交叉类型 (Intersection Types)

交叉类型将多个类型合并为一个类型。

TypeScript 复制代码
interface BusinessPartner {
  name: string;
  credit: number;
}

interface Identity {
  id: number;
  name: string;
}

type Employee = BusinessPartner & Identity;

let emp: Employee = {
  id: 100,
  name: "John",
  credit: 7000,
};

// 添加输出语句
console.log("=== 交叉类型示例 ===");
console.log("员工信息:");
console.log(`ID: ${emp.id}`);
console.log(`姓名: ${emp.name}`);
console.log(`信用额度: ${emp.credit}`);


// 使用函数处理交叉类型
function displayEmployeeInfo(employee: Employee): void {
  console.log(`
员工 ${employee.name} (ID: ${employee.id}) 的信用额度为 ${employee.credit}`);
}

displayEmployeeInfo(emp);

// 检查属性是否存在
function hasHighCredit(employee: Employee): boolean {
  return employee.credit > 7500;
}

console.log("=== 信用额度检查 ===");
console.log(`${emp.name} 是否有高信用额度: ${hasHighCredit(emp)}`);

6. 类型守卫 (Type Guards)

类型守卫是一些表达式,它们在运行时检查类型,帮助 TypeScript 缩小类型范围。

TypeScript 复制代码
// 使用 typeof 的类型守卫
function padLeft(value: string, padding: string | number): string {
  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}'.`);
}

// 使用 in 操作符的类型守卫
interface Car {
  drive(): void;
}

interface Boat {
  sail(): void;
}

function useVehicle(vehicle: Car | Boat) {
  if ("drive" in vehicle) {
    vehicle.drive(); // TypeScript 知道这是 Car
  } else {
    vehicle.sail(); // TypeScript 知道这是 Boat
  }
}

// 添加输出语句
console.log("=== 类型守卫示例 ===");
console.log(`"${padLeft("Hello", 5)}"`);
console.log(`"${padLeft("World", "---")}"`);

const myCar: Car = {
  drive: () => console.log("汽车正在行驶...")
};

const myBoat: Boat = {
  sail: () => console.log("小船正在航行...")
};

console.log("使用汽车:");
useVehicle(myCar);
console.log("使用小船:");
useVehicle(myBoat);

7. 空值检查 (Null Checks)

TypeScript 提供了严格的空值检查选项,帮助避免常见的空引用错误。

TypeScript 复制代码
// 启用严格空值检查后
function getNameFromUser(user?: { name: string }): string {
    // 错误: 'user' 可能为 'undefined'
    // return user.name;
    
    // 正确方式
    if (user) {
        return user.name;
    }
    return "Anonymous";
}

// 非空断言操作符
function getDisplayName(user: { name: string } | null): string {
    // 告诉 TypeScript 我们确定 user 不为 null
    return user!.name;
}

8. 模块系统

TypeScript 支持现代 JavaScript 模块系统,使代码组织更加清晰。

TypeScript 复制代码
// math.ts
const add = (x: number, y: number): number => {
  return x + y;
};

function subtract(x: number, y: number): number {
  return x - y;
}

module.exports = {
  add,
  subtract,
};
// app.ts
const { add, subtract } = require("./math");

console.log(add(5, 3)); // 8
console.log(subtract(10, 4)); // 6

// 默认导出
class Calculator {
  add(x: number, y: number): number {
    return x + y;
  }
}

// 导入默认导出
module.exports = Calculator;

在 "verbatimModuleSyntax" 模式下,不允许在 CommonJS 模块中使用 ESM 语法

9. 高级类型技巧

映射类型 (Mapped Types)

TypeScript 复制代码
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

type Partial<T> = {
  [P in keyof T]?: T[P];
};

interface User {
  name: string;
  age: number;
}

// 创建一个所有属性都是只读的 User 类型
type ReadonlyUser = Readonly<User>;

// 创建一个所有属性都是可选的 User 类型
type PartialUser = Partial<User>;

// 添加输出语句
console.log("=== 映射类型示例 ===");

const user: User = { name: "Alice", age: 30 };
console.log("原始用户:", user);

const readonlyUser: ReadonlyUser = { name: "Bob", age: 25 };
console.log("只读用户:", readonlyUser);

const partialUser: PartialUser = { name: "Charlie" };
console.log("部分用户:", partialUser);

条件类型 (Conditional Types)

TypeScript 复制代码
type NonNullable<T> = T extends null | undefined ? never : T;

type ExtractType<T, U> = T extends U ? T : never;

// 示例
type StringOrNumber = string | number;
type OnlyString = ExtractType<StringOrNumber, string>; // string

// 添加输出语句
console.log("=== 条件类型示例 ===");

// NonNullable 示例
const nullableString: string | null = "Hello";
const nonNullString: NonNullable<string | null> = "World";

console.log("可为空的字符串:", nullableString);
console.log("非空字符串:", nonNullString);

// ExtractType 示例
const stringOrNumber: StringOrNumber = "TypeScript";
console.log("字符串或数字:", stringOrNumber);
console.log("OnlyString 类型检查:", typeof stringOrNumber === "string" ? "是字符串" : "不是字符串");

10. 类型推断

TypeScript 能够根据上下文自动推断类型,减少显式类型注解的需要。

TypeScript 复制代码
// 类型推断示例
let x = 3; // TypeScript 推断 x 的类型为 number

// 函数返回类型推断
function add(a: number, b: number) {
  return a + b; // TypeScript 推断返回类型为 number
}

// 添加输出语句
console.log("=== 类型推断示例 ===");
console.log("变量 x 的值:", x);
console.log("变量 x 的类型:", typeof x);

const sum = add(5, 7);
console.log("add(5, 7) 的结果:", sum);
console.log("sum 的类型:", typeof sum);

// 上下文推断示例
console.log("=== 上下文推断示例 ===");

// 定义一个简单的函数来演示上下文推断
function handleMouseDown(mouseEvent: { button: number }) {
  console.log("鼠标按钮:", mouseEvent.button);
}

// 模拟鼠标点击事件
console.log("模拟鼠标点击事件:");
handleMouseDown({ button: 0 }); // 左键点击

11. 声明文件与 DefinitelyTyped

TypeScript 使用声明文件(.d.ts)来描述 JavaScript 库的类型。

TypeScript 复制代码
// 声明全局变量
declare var $: (selector: string) => any;

// 声明模块
declare module "my-library" {
    export function doSomething(): void;
}

通过 DefinitelyTyped,大多数流行的 JavaScript 库都有可用的类型定义:

TypeScript 复制代码
npm install --save-dev @types/node @types/react @types/express

TypeScript 提前支持了一些还未在所有环境中普及的 ES 特性,如装饰器(Decorators)、异步迭代器等

总结

TypeScript 的这些特性使它成为大型项目开发的理想选择:

  1. 类型安全:在编译时捕获错误,减少运行时问题
  2. 更好的代码组织:通过接口、类和模块系统
  3. 增强的工具支持:提供精确的代码补全、重构和导航
  4. 现代 JavaScript 特性:支持最新的 ECMAScript 标准
  5. 渐进式采用:可以逐步将 JavaScript 项目迁移到 TypeScript

TypeScript 基础语法

TypeScript 基础语法 | 菜鸟教程

tsc 常用编译参数如下表所示:

序号 编译参数说明
1. --help 显示帮助信息
2. --module 载入扩展模块,需要一个参数
3. --target 设置 ECMA 版本,需要一个参数
4. --declaration 额外生成一个 .d.ts 扩展名的文件。 tsc ts-hw.ts --declaration 以上命令会生成 ts-hw.d.ts、ts-hw.js 两个文件。
5. --removeComments 删除文件的注释
6. --out 编译多个文件并合并到一个输出的文件
7. --sourcemap 生成一个 sourcemap (.map) 文件。 sourcemap 是一个存储源代码与编译代码对应位置映射的信息文件。
8. --module noImplicitAny 在表达式和声明上有隐含的 any 类型时报错
9. --watch 在监视模式下运行编译器。会监视输出文件,在它们改变时重新编译。

tsc --help

tsc --module

tsc--target

tsc --removeComments

TypeScript 注释

注释用于解释代码,提高代码可读性。

单行注释

TypeScript 复制代码
// 这是一个单行注释
let count: number = 0; // 初始化计数器

// 函数说明:计算两个数的和
function add(a: number, b: number): number {
  return a + b; // 返回计算结果
}

多行注释

TypeScript 复制代码
/*
 * 这是一个多行注释
 * 用于详细解释函数的功能
 * 参数说明:
 * @param name 用户姓名
 * @param age 用户年龄
 * @returns 用户信息字符串
 */
function createUserProfile(name: string, age: number): string {
  return `姓名: ${name}, 年龄: ${age}`;
}

/**
 * 计算圆的面积
 * @param radius 圆的半径
 * @returns 圆的面积
 * @throws {Error} 当半径为负数时抛出错误
 */
function calculateCircleArea(radius: number): number {
  if (radius < 0) {
    throw new Error("半径不能为负数");
  }
  return Math.PI * radius * radius;
}

JSDoc 注释

TypeScript 复制代码
/**
 * 用户类
 * @class
 * @classdesc 表示系统中的用户实体
 */
class User {
  /**
   * 用户ID
   * @type {number}
   */
  public id: number;
  
  /**
   * 用户名
   * @type {string}
   */
  public name: string;
  
  /**
   * 创建用户实例
   * @param {number} id - 用户ID
   * @param {string} name - 用户名
   * @param {number} [age] - 用户年龄(可选)
   */
  constructor(id: number, name: string, age?: number) {
    this.id = id;
    this.name = name;
  }
  
  /**
   * 获取用户信息
   * @returns {string} 用户信息字符串
   */
  getInfo(): string {
    return `ID: ${this.id}, 姓名: ${this.name}`;
  }
}

TypeScript 基本结构

TypeScript 基本结构 | 菜鸟教程

TypeScript 基础类型

TypeScript 基础类型 | 菜鸟教程

TypeScript 复制代码
// 定义枚举类型,用于表示用户的角色
enum Role {
  Admin,
  User,
  Guest,
}

// 使用 interface 定义用户的结构
interface User {
  id: number;               // number 类型,用于唯一标识用户
  username: string;         // string 类型,表示用户名
  isActive: boolean;        // boolean 类型,表示用户是否激活
  role: Role;               // enum 类型,用于表示用户角色
  hobbies: string[];        // array 类型,存储用户的兴趣爱好
  contactInfo: [string, number]; // tuple 类型,包含电话号码的元组,格式为:[区域码, 电话号码]
}

// 创建用户对象,符合 User 接口的结构
const user: User = {
  id: 1,
  username: "Alice",
  isActive: true,
  role: Role.User,
  hobbies: ["Reading", "Gaming"],
  contactInfo: ["+1", 123456789],
};

// 定义一个返回字符串的函数来获取用户信息
function getUserInfo(user: User): string {
  return `User ${user.username} is ${user.isActive ? "active" : "inactive"} with role ${Role[user.role]}`;
}

// 使用 void 类型定义一个函数,专门打印用户信息
function printUserInfo(user: User): void {
  console.log(getUserInfo(user));
}

// 定义一个 union 类型的函数参数,接受用户 ID(number)或用户名(string)
function findUser(query: number | string): User | undefined {
  // 使用 typeof 来判断 query 的类型
  if (typeof query === "number") {
    // 如果是数字,则根据 ID 查找用户
    return query === user.id ? user : undefined;
  } else if (typeof query === "string") {
    // 如果是字符串,则根据用户名查找用户
    return query === user.username ? user : undefined;
  }
  return undefined;
}

// 定义一个 never 类型的函数,用于处理程序的异常情况
function throwError(message: string): never {
  throw new Error(message);
}

// 使用 any 类型处理未知类型的数据
let unknownData: any = "This is a string";
unknownData = 42; // 重新赋值为数字,类型为 any

// 使用 unknown 类型处理不确定的数据,更加安全
let someData: unknown = "Possible data";
if (typeof someData === "string") {
  console.log(`Length of data: ${(someData as string).length}`);
}

// 调用各个函数并测试
printUserInfo(user);                    // 打印用户信息
console.log(findUser(1));               // 根据 ID 查找用户
console.log(findUser("Alice"));         // 根据用户名查找用户

// 使用 null 和 undefined 类型的变量
let emptyValue: null = null;
let uninitializedValue: undefined = undefined;

TypeScript 变量声明

**注意:**变量不要使用 name 否则会与 DOM 中的全局 window 对象下的 name 属性出现了重名。

类型断言

TypeScript 复制代码
var str = "1";
var str2: number = <number>(<any>str); //str、str2 是 string 类型
console.log(str2);

类型判断

TypeScript 变量声明

TypeScript 主要包含以下几种运算:

  • 算术运算符
  • 逻辑运算符
  • 关系运算符
  • 按位运算符
  • 赋值运算符
  • 三元/条件运算符
  • 字符串运算符
  • 类型运算符

TypeScript 条件语句

TypeScript 条件语句 | 菜鸟教程

TypeScript 循环

TypeScript 循环 | 菜鸟教程

for...of 、forEach、every 和 some 循环

1. for...of 循环

for...of 是 ES6 引入的一种遍历可迭代对象(包括数组、字符串、Map、Set 等)的语法结构。

TypeScript 复制代码
// 基本语法
const numbers: number[] = [1, 2, 3, 4, 5];

for (const num of numbers) {
  console.log(num);
}

// 遍历字符串
const greeting: string = "Hello";
for (const char of greeting) {
  console.log(char); // H e l l o
}

// 在 for...of 中获取索引
const fruits: string[] = ["apple", "banana", "orange"];
for (const [index, fruit] of fruits.entries()) {
  console.log(`${index}: ${fruit}`);
}

2. forEach 方法

forEach 是数组的一个方法,对数组的每个元素执行一次提供的函数。

TypeScript 复制代码
// 基本用法
const numbers: number[] = [1, 2, 3, 4, 5];
numbers.forEach((num) => {
  console.log(num);
});

// 带索引的用法
const colors: string[] = ["red", "green", "blue"];
colors.forEach((color, index) => {
  console.log(`${index}: ${color}`);
});

// 完整回调函数参数
colors.forEach((color, index, array) => {
  console.log(`${index}: ${color}`, array);
});

// 使用 thisArg 参数
const counter = {
  count: 0,
  increment: function(value: number) {
    this.count += value;
    console.log(`Current count: ${this.count}`);
  }
};

const values = [10, 20, 30];
values.forEach(function(value) {
  this.increment(value);
}, counter);

3. every 方法

every 方法测试数组中的所有元素是否都通过了指定函数的测试。它返回一个布尔值。

TypeScript 复制代码
// 检查所有元素是否满足条件
const numbers = [2, 4, 6, 8, 10];
const allEven = numbers.every((num) => num % 2 === 0);
console.log(allEven); // true

const mixedNumbers = [1, 2, 4, 6];
const allEvenMixed = mixedNumbers.every((num) => num % 2 === 0);
console.log(allEvenMixed); // false

// 实际应用场景
const users = [
  { name: "Alice", age: 25, active: true },
  { name: "Bob", age: 30, active: true },
  { name: "Charlie", age: 35, active: true }
];

// 检查所有用户是否都是活跃的
const allActive = users.every(user => user.active);
console.log(allActive); // true

// 检查所有用户是否都成年
const allAdults = users.every(user => user.age >= 18);
console.log(allAdults); // true

4. some 方法

some 方法测试数组中是否至少有一个元素通过了指定函数的测试。它返回一个布尔值。

TypeScript 复制代码
// 检查是否有元素满足条件
const numbers = [1, 3, 5, 8, 10];
const hasEven = numbers.some((num) => num % 2 === 0);
console.log(hasEven); // true

const allOdd = [1, 3, 5, 7];
const hasEvenOdd = allOdd.some((num) => num % 2 === 0);
console.log(hasEvenOdd); // false

// 实际应用场景
const products = [
  { name: "Laptop", price: 1000, inStock: true },
  { name: "Mouse", price: 25, inStock: false },
  { name: "Keyboard", price: 75, inStock: true }
];

// 检查是否有缺货商品
const hasOutOfStock = products.some(product => !product.inStock);
console.log(hasOutOfStock); // true

// 检查是否有高价商品
const hasExpensive = products.some(product => product.price > 500);
console.log(hasExpensive); // true

方法比较与使用场景

方法 返回值 用途 是否可中断
for...of 遍历元素并执行操作 可以使用 break 中断
forEach 遍历元素并执行操作 不可中断
every 布尔值 检查所有元素是否满足条件 在第一个不满足条件的元素处停止
some 布尔值 检查是否有元素满足条件 在第一个满足条件的元素处停止

性能考虑

  • 对于大型数组, for...of 循环通常比 forEach 更快,因为它是语言级别的结构,减少了函数调用的开销
  • everysome 具有短路行为,在找到匹配项时会立即停止遍历,这比手动遍历整个数组更高效
  • 如果需要在遍历过程中提前退出,使用 for...of 配合 breakreturn 是更好的选择

TypeScript 函数

TypeScript 函数 | 菜鸟教程

在 TypeScript 函数里,如果我们定义了参数,则我们必须传入这些参数,除非将这些参数设置为可选,可选参数使用问号标识 ?。

函数的最后一个命名参数以 ... 为前缀,它将成为一个由剩余参数组成的数组,索引值从0(包括)到.length(不包括)。

TypeScript Number

TypeScript Number | 菜鸟教程

TypeScript String(字符串)

TypeScript String(字符串) | 菜鸟教程

通常情况下,TypeScript 推荐直接使用 string 字面量类型,以简化代码,提高性能,避免不必要的类型转换和复杂性。

TypeScript Array(数组)

TypeScript Array(数组) | 菜鸟教程

TypeScript Map 对象

TypeScript Map 对象 | 菜鸟教程

TypeScript 元组

TypeScript 元组 | 菜鸟教程

TypeScript 联合类型

TypeScript 联合类型 | 菜鸟教程

TypeScript 接口

TypeScript 接口 | 菜鸟教程

TypeScript 命名空间

TypeScript 命名空间 | 菜鸟教程

TypeScript 中命名空间使用 namespace 来定义

TypeScript 模块

TypeScript 模块 | 菜鸟教程

JavaScript模块加载器是服务于 Node.js 的 CommonJS 和服务于 Web 应用的 Require.js

TypeScript 声明文件

TypeScript 声明文件 | 菜鸟教程

declare 关键字来定义它的类型,帮助 TypeScript 判断我们传入的参数类型对不对

declare 定义的类型只会用于编译时的检查,编译结果中会被删除。

声明文件

声明文件以 .d.ts 为后缀

相关推荐
kk晏然12 分钟前
TypeScript 错误类型检查,前端ts错误指南
前端·react native·typescript·react
科技林总20 分钟前
【系统分析师】3.3 输入输出系统
学习
纆兰22 分钟前
汇款单的完成
前端·javascript·html
进阶小白猿30 分钟前
Java技术八股学习Day17
java·jvm·学习
whale fall33 分钟前
【雅思听力语料库5.1】
笔记·学习
Lsx_40 分钟前
案例+图解带你遨游 Canvas 2D绘图 Fabric.js🔥🔥(5W+字)
前端·javascript·canvas
2501_944521001 小时前
rn_for_openharmony商城项目app实战-主题设置实现
javascript·数据库·react native·react.js·ecmascript
m0_471199631 小时前
【场景】如何快速接手一个前端项目
前端·vue.js·react.js
榴莲CC1 小时前
抗干扰LED数显屏驱动VK1624 数码管显示芯片 3线串行接口
前端
lili-felicity1 小时前
React Native for Harmony 个人消息列表最新消息置顶实现(多维度权重统计)
javascript·react native·react.js