这篇教程是用于本人学习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了。先学习基础知识,在实际项目中逐步学习更高级的特性。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。