当前位置 : 首页 » 文章分类 :   »  TypeScript

TypeScript

JavaScript 是弱类型语言,TypeScript 的核心价值就是给 JavaScript 提供​​静态类型检查​​。

TypeScript
https://www.typescriptlang.org/


NPM 安装 TypeScript 编译器

https://www.npmjs.com/package/typescript

npm install typescript --save-dev

typescript 包提供 TypeScript 的编译器和语言服务
typescript 包提供 tsc 命令,用于将 .ts 或 .tsx 文件编译成 JavaScript


tsc 命令


tsconfig.json 配置文件

tsconfig.json 定义编译规则,如输出目录、目标 JS 版本等


@types/* JS 类型检查包

为​​纯 JavaScript 编写的库​​提供 TypeScript 类型定义,使得在使用 JS 库时获得 TS 的类型提示和检查

@types/* 包来源:

  • DefinitelyTyped:约占 85%
  • 包自带:约占 10%
  • TS 内置类型:约占 5%

DefinitelyTyped

@types/* 包的约 85% 由 DefinitelyTyped 社区维护和发布
https://github.com/DefinitelyTyped/DefinitelyTyped

DefinitelyTyped 运行机制

  • 当 JS 库(如 lodash)无自带类型时,社区为其编写类型声明文件( .d.ts
  • 通过自动化工具发布到 npm,命名规范为 @types/[包名]

ts-node TypeScript 即时编译及交互环境

https://www.npmjs.com/package/ts-node
ts-node 是一个用于在 Node.js 环境中直接运行 TypeScript 代码的 npm 包,无需手动编译成 JavaScript。

TypeScript 即时编译(JIT)
ts-node 在内存中实时将 TypeScript 代码转换为 JavaScript(通过 TypeScript 编译器),省略了 tsc > node 的中间步骤。
ts-node script.ts 即可直接执行 script.ts

TypeScript REPL(Read Eval Print Loop) 交互式环境
提供交互式 TypeScript REPL(类似 Node.js 的 node命令),直接输入 TypeScript 代码并查看结果

ts-node 本身​​不包含​​ TypeScript 编译器(tsc),它需要依赖 typescript 包来完成编译工作。
安装 ts-node 时不会自动安装 typescript,所以最佳实践是 ts-node 和 typescript 一起安装
npm install ts-node typescript --save-dev


TypeScript 类型注解

变量类型标注

// 类型注解 - 显式指定类型
let message: string = "Hello";

// 类型推断 - TypeScript 自动推断类型
let inferredString = "This is a string"; // 推断为 string
let inferredNumber = 42; // 推断为 number

函数类型标注

// 函数参数和返回值的类型注解
function greet(name: string): string {
    return `Hello, ${name}`;
}

TypeScript 类型体操

Type Challenges
https://github.com/type-challenges/type-challenges

JavaScript 基本类型

// 基本类型
let isDone: boolean = false;
let count: number = 42;
let name: string = "TypeScript";

// 数组
let list: number[] = [1, 2, 3];
let genericList: Array<number> = [1, 2, 3]; // 泛型语法

// 元组 - 固定类型和长度的数组
let tuple: [string, number] = ["hello", 10];

// 任意类型 - 绕过类型检查
let notSure: any = 4;
notSure = "maybe a string";

// 空值
let unusable: void = undefined;
let nullValue: null = null;
let undefinedValue: undefined = undefined;

// Never 类型 - 表示永远不会发生的值
function error(message: string): never {
    throw new Error(message);
}

可选类型 ?

通过 ? 修饰符标记 属性/参数 为可选,表示该值允许为 undefined 或完全不存在

  • 允许该字段不存在​​:定义对象时可以不包含该属性
  • 自动添加 undefined类型​​:访问时类型会变成 原类型 | undefined
// 接口可选属性
interface User {
  id: string;
  email?: string; // 可选属性
}

// 类型别名可选属性
type Product = {
  name: string;
  price?: number; // 可选属性
}

// 函数可选参数
function logMessage(message: string, prefix?: string) {
  // prefix 是可选的
}

以下两种声明等效:

interface Example1 { prop?: string }
interface Example2 { prop: string | undefined }

可选链操作符 ?.

可选链操作符 ?. 是 TypeScript 3.7 引入的重要特性,用于简化深层嵌套属性的安全访问。

可选链访问深层嵌套属性

例如有如下深层嵌套类

interface Company {
  name: string;
  CEO?: {
    profile?: {
      age?: number;
      contact?: {
        email?: string;
      };
    };
  };
}

想要获取深层的 email 属性,可选链操作符可大大简化代码:

// 传统深层访问需要大量判断
const email = company.CEO && 
              company.CEO.profile && 
              company.CEO.profile.contact && 
              company.CEO.profile.contact.email;

// 使用可选链 - 一行搞定
const email2 = company.CEO?.profile?.contact?.email; // undefined

可选链函数调用

class ApiService {
  getData?(): { result: string } {
    return { result: "success" };
  }
}

const service1 = new ApiService();
const service2: ApiService = {}; // 没有 getData 方法

// 安全调用可能不存在的方法
const result1 = service1.getData?.(); // { result: "success" }
const result2 = service2.getData?.(); // undefined,不会报错

// 与空值合并运算符结合使用
const safeResult = service2.getData?.() ?? { result: "default" };
console.log(safeResult); // { result: "default" }

可选链访问数组元素

interface UserList {
  users?: Array<{ name: string; age?: number }>;
}

const data1: UserList = {
  users: [{ name: "Alice", age: 25 }, { name: "Bob" }]
};

const data2: UserList = {}; // 没有 users 数组

// 安全访问数组元素
const firstUserName1 = data1.users?.[0]?.name; // "Alice"
const firstUserAge1 = data1.users?.[0]?.age;  // 25
const secondUserAge1 = data1.users?.[1]?.age; // undefined

const firstUserName2 = data2.users?.[0]?.name; // undefined

条件类型

// 条件类型
type TypeName<T> =
    T extends string ? "string" :
    T extends number ? "number" :
    T extends boolean ? "boolean" :
    "object";

Union Types 联合类型 |

let value: string | null = null;    // 可以是字符串或 null
let data: number | undefined;       // 可以是数字或 undefined

// 联合类型 - 可以是多种类型之一
let union: string | number;
union = "hello";
union = 42;

交叉类型

// 交叉类型 - 同时具有多种类型的特性
interface A { a: number }
interface B { b: string }
type C = A & B; // { a: number, b: string }

let obj: C = { a: 1, b: "hello" };

类型别名/自定义类型

可以通过自定义类型,实现类似 Python typing 中的 Optional 类型

type Optional<T> = T | null;
type Maybe<T> = T | null | undefined; // 包含 undefined
type Point = {
    x: number;
    y: number;
};

// 使用示例
let port: Optional<MessagePort> = null;
let data: Maybe<string> = undefined;

空值合并操作符 ??

空值合并操作符(Nullish Coalescing Operator) ?? 是 ES2020 引入的重要特性

基本语法:leftExpr ?? rightExpr
执行逻辑:如果左侧表达式是 null 或 undefined,则返回右侧表达式;否则返回左侧表达式。

console.log(null ?? "default"); // "default",因为 null 是 nullish
console.log(undefined ?? "default"); // "default",因为 undefined 是 nullish
console.log("" ?? "default"); // "" 空字符串不是 nullish,所以返回空字符串
console.log(0 ?? 100); // 0 数字0不是 nullish,所以返回0
console.log(false ?? true); // false false 不是 nullish,所以返回 false

与逻辑或操作符 || 对比

console.log(null || "default"); // "default"
console.log(undefined || "default"); // "default"

console.log(("" || "default"); // "default" 空字符串是假值,所以逻辑或会返回右侧
console.log(0 || 100); // 100  0 是假值,所以逻辑或返回右侧
console.log(false || true); // true   false 是假值,所以逻辑或返回右侧

上一篇 JavaScript-基础

下一篇 NPM-Basic

阅读
评论
1.6k
阅读预计7分钟
创建日期 2025-08-21
修改日期 2025-11-14

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论