TypeScript基本教程,10分钟快速掌握TypeScript

这篇教程是用于本人学习TypeScript的记录,TypeScript和JavaScript写法基本一致,只是需要给变量定义类型,通过了解如何给常用的结构定义类型,基本就可以TypeScript了。

1. 什么是 TypeScript?

TypeScript 是 JavaScript 的超集,添加了静态类型检查。简单来说:

  • JavaScript = 动态类型,运行时才知道错误
  • TypeScript = 静态类型,编写时就能发现错误
// JavaScript - 运行时才发现错误
let user = "张三";
user.age = 25; // 运行时错误:字符串没有 age 属性

// TypeScript - 编写时就发现错误
let user: string = "张三";
user.age = 25; // 编译时错误:类型 'string' 上不存在属性 'age'

2. 基本类型

2.1 原始类型

// 字符串
let name: string = "张三";
let message: string = `你好,${name}!`;

// 数字
let age: number = 25;
let price: number = 99.99;

// 布尔值
let isStudent: boolean = true;
let isTeacher: boolean = false;

// 空值
let nothing: null = null;
let undefined: undefined = undefined;

2.2 数组

// 数组的两种写法
let numbers: number[] = [1, 2, 3, 4, 5];
let strings: Array<string> = ["apple", "banana", "orange"];

// 混合类型数组
let mixed: (string | number)[] = ["hello", 42, "world"];

2.3 对象

// 简单对象
let user: { name: string; age: number } = {
  name: "张三",
  age: 25
};

// 可选属性 (?)
let product: { name: string; price: number; description?: string } = {
  name: "iPhone",
  price: 999
  // description 是可选的,可以不写
};

3. 接口 (Interface)

接口用来定义对象的结构,是 TypeScript 中最重要的概念之一。

// 定义用户接口
interface User {
  id: number;
  name: string;
  email: string;
  age?: number;        // 可选属性
  isActive: boolean;
}

// 使用接口
let user: User = {
  id: 1,
  name: "张三",
  email: "zhangsan@example.com",
  isActive: true
};

// 函数参数使用接口
function greetUser(user: User): string {
  return `你好,${user.name}!`;
}

3.1 扩展接口

// 基础接口
interface Person {
  name: string;
  age: number;
}

// 扩展接口
interface Student extends Person {
  studentId: string;
  grade: number;
}

// 使用扩展接口
let student: Student = {
  name: "李四",
  age: 20,
  studentId: "S001",
  grade: 95
};

4. 类型别名 (Type Alias)

// 基本类型别名
type Status = "pending" | "success" | "error";
type ID = string | number;

// 对象类型别名
type Point = {
  x: number;
  y: number;
};

// 使用类型别名
let currentStatus: Status = "pending";
let userId: ID = "user123";
let coordinate: Point = { x: 10, y: 20 };

5. 联合类型和交叉类型

5.1 联合类型 (|)

// 变量可以是多种类型之一
let id: string | number;
id = "abc123";  // 正确
id = 123;       // 正确
id = true;      // 错误

// 函数参数使用联合类型
function formatId(id: string | number): string {
  return `ID: ${id}`;
}

5.2 交叉类型 (&)

// 组合多个类型
type Name = { name: string };
type Age = { age: number };
type Person = Name & Age;

let person: Person = {
  name: "张三",
  age: 25
};

6. 函数类型

// 函数声明
function add(a: number, b: number): number {
  return a + b;
}

// 箭头函数
const multiply = (a: number, b: number): number => {
  return a * b;
};

// 可选参数
function greet(name: string, greeting?: string): string {
  return `${greeting || "你好"},${name}!`;
}

// 默认参数
function createUser(name: string, age: number = 18): User {
  return { id: 1, name, email: "", age, isActive: true };
}

// 函数类型别名
type Calculator = (a: number, b: number) => number;
const divide: Calculator = (a, b) => a / b;

7. 泛型 (Generics)

泛型让你的代码更加灵活和可重用。

// 基本泛型函数
function identity<T>(arg: T): T {
  return arg;
}

// 使用泛型
let output1 = identity<string>("hello");
let output2 = identity<number>(42);

// 泛型接口
interface ApiResponse<T> {
  data: T;
  success: boolean;
  message: string;
}

// 使用泛型接口
let userResponse: ApiResponse<User> = {
  data: { id: 1, name: "张三", email: "zhangsan@example.com", isActive: true },
  success: true,
  message: "获取用户成功"
};

// 泛型约束
interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(arg: T): T {
  console.log(arg.length);
  return arg;
}

8. 枚举 (Enum)

// 数字枚举
enum UserRole {
  USER,      // 0
  ADMIN,     // 1
  MODERATOR  // 2
}

// 字符串枚举
enum Status {
  PENDING = "pending",
  SUCCESS = "success",
  ERROR = "error"
}

// 使用枚举
let userRole: UserRole = UserRole.ADMIN;
let apiStatus: Status = Status.SUCCESS;

9. 类 (Class)

class Animal {
  // 属性
  private name: string;
  protected age: number;
  public species: string;

  // 构造函数
  constructor(name: string, age: number, species: string) {
    this.name = name;
    this.age = age;
    this.species = species;
  }

  // 方法
  public makeSound(): string {
    return "Some sound";
  }

  // 获取器
  get getName(): string {
    return this.name;
  }
}

// 继承
class Dog extends Animal {
  private breed: string;

  constructor(name: string, age: number, breed: string) {
    super(name, age, "犬科");
    this.breed = breed;
  }

  public makeSound(): string {
    return "汪汪!";
  }
}

// 使用类
let myDog = new Dog("小白", 3, "拉布拉多");
console.log(myDog.makeSound()); // "汪汪!"

10. 模块和导入导出

// types.ts - 导出类型
export interface User {
  id: number;
  name: string;
  email: string;
}

export type UserRole = "admin" | "user" | "moderator";

// utils.ts - 导出函数
export function formatDate(date: Date): string {
  return date.toLocaleDateString();
}

export const API_URL = "https://api.example.com";

// main.ts - 导入和使用
import { User, UserRole } from "./types";
import { formatDate, API_URL } from "./utils";

const user: User = {
  id: 1,
  name: "张三",
  email: "zhangsan@example.com"
};

const role: UserRole = "admin";

11. 在 Nuxt 中使用 TypeScript

11.1 Vue 组件中的 TypeScript

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>用户: {{ user.name }}</p>
    <button @click="updateUser">更新用户</button>
  </div>
</template>

<script setup lang="ts">
// 导入类型
interface User {
  id: number;
  name: string;
  email: string;
}

// 定义响应式数据
const title = ref<string>("用户管理");
const user = ref<User>({
  id: 1,
  name: "张三",
  email: "zhangsan@example.com"
});

// 定义方法
const updateUser = (): void => {
  user.value.name = "李四";
};

// 计算属性
const userInfo = computed((): string => {
  return `${user.value.name} (${user.value.email})`;
});
</script>

11.2 API 类型定义

// types/api.ts
export interface ApiResponse<T> {
  data: T;
  success: boolean;
  message: string;
  code: number;
}

export interface LoginRequest {
  email: string;
  password: string;
}

export interface LoginResponse {
  token: string;
  user: User;
}

// composables/useAuth.ts
export const useAuth = () => {
  const login = async (credentials: LoginRequest): Promise<LoginResponse> => {
    const response = await $fetch<ApiResponse<LoginResponse>>("/api/auth/login", {
      method: "POST",
      body: credentials
    });
    
    if (response.success) {
      return response.data;
    }
    
    throw new Error(response.message);
  };

  return { login };
};

12. 常用实用类型

TypeScript 提供了许多实用类型来帮助你处理常见的类型转换。

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
}

// Partial - 所有属性变为可选
type PartialUser = Partial<User>;
// 等同于: { id?: number; name?: string; email?: string; password?: string; }

// Required - 所有属性变为必需
type RequiredUser = Required<PartialUser>;

// Pick - 选择特定属性
type PublicUser = Pick<User, 'id' | 'name' | 'email'>;
// 等同于: { id: number; name: string; email: string; }

// Omit - 排除特定属性
type UserWithoutPassword = Omit<User, 'password'>;
// 等同于: { id: number; name: string; email: string; }

// Record - 创建对象类型
type UserRoles = Record<string, UserRole>;
// 等同于: { [key: string]: UserRole; }

13. 错误处理

// 自定义错误类型
class ValidationError extends Error {
  constructor(public field: string, message: string) {
    super(message);
    this.name = "ValidationError";
  }
}

// 使用 try-catch
async function createUser(userData: Partial<User>): Promise<User> {
  try {
    if (!userData.name) {
      throw new ValidationError("name", "用户名不能为空");
    }
    
    // 创建用户逻辑
    return userData as User;
  } catch (error) {
    if (error instanceof ValidationError) {
      console.error(`验证错误 - ${error.field}: ${error.message}`);
    }
    throw error;
  }
}

14. 配置文件 (tsconfig.json)

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "outDir": "./dist",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "~/*": ["./src/*"]
    }
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

15. 实践建议

15.1 类型定义最佳实践

// ❌ 避免使用 any
let data: any = getData();

// ✅ 使用具体类型
interface ApiData {
  id: number;
  name: string;
}
let data: ApiData = getData();

// ❌ 避免过度复杂的类型
type ComplexType = {
  [K in keyof SomeType]: SomeType[K] extends string ? number : boolean;
};

// ✅ 保持类型简单明了
interface SimpleUser {
  id: number;
  name: string;
  isActive: boolean;
}

15.2 常见错误和解决方案

// 错误: 对象可能为 null
const user = getUser(); // 可能返回 null
console.log(user.name); // 错误

// 解决方案 1: 类型守卫
if (user) {
  console.log(user.name);
}

// 解决方案 2: 可选链
console.log(user?.name);

// 解决方案 3: 空值合并
console.log(user?.name ?? "未知用户");

16. 快速参考

16.1 常用类型声明

// 基本类型
let str: string = "hello";
let num: number = 42;
let bool: boolean = true;
let arr: string[] = ["a", "b", "c"];
let obj: { name: string; age: number } = { name: "张三", age: 25 };

// 函数类型
type Callback = (data: string) => void;
const fn: Callback = (data) => console.log(data);

// 联合类型
let status: "loading" | "success" | "error" = "loading";

// 泛型
function identity<T>(arg: T): T { return arg; }

16.2 常用关键字

  • interface - 定义对象结构
  • type - 创建类型别名
  • extends - 继承接口或类
  • implements - 实现接口
  • keyof - 获取对象键的联合类型
  • typeof - 获取变量的类型
  • as - 类型断言
  • ? - 可选属性
  • ! - 非空断言

通过这些基础知识,基本可以在日常项目中使用TypeScript了。先学习基础知识,在实际项目中逐步学习更高级的特性。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

给TA打赏
共{{data.count}}人
人已打赏
技术教程

快速部署MaxKB实现AI知识库问答教程

2025-2-27 13:45:33

技术教程

Deepseek总提示“服务器繁忙”?试试这个完全免费的替代品吧

2025-2-5 14:16:54

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索