阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 泛型接口

泛型接口

作者:陈川 阅读数:28640人阅读 分类: TypeScript

泛型接口的基本概念

泛型接口允许我们创建可重用的组件,这些组件可以处理多种类型而不是单一类型。TypeScript中的泛型接口通过在接口定义中使用类型参数来实现这一点。类型参数在接口名称后面的尖括号中声明,可以在接口的属性和方法中使用。

interface GenericIdentityFn<T> {
  (arg: T): T;
}

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

let myIdentity: GenericIdentityFn<number> = identity;

泛型接口的语法结构

泛型接口的语法与普通接口类似,但在接口名称后添加了类型参数。类型参数可以是任何有效的标识符,通常使用单个大写字母如T、U、V等。这些类型参数可以在接口的各个部分使用,包括属性类型、方法参数类型和返回类型。

interface KeyValuePair<K, V> {
  key: K;
  value: V;
}

let pair1: KeyValuePair<number, string> = { key: 1, value: "one" };
let pair2: KeyValuePair<string, boolean> = { key: "isValid", value: true };

泛型接口与函数

泛型接口常用于描述函数类型,这使得我们可以创建灵活的函数签名。函数泛型接口可以指定参数类型和返回类型之间的关系,同时保持类型安全。

interface Transformer<T, U> {
  (input: T): U;
}

const stringToNumber: Transformer<string, number> = (str) => parseFloat(str);
const numberToString: Transformer<number, string> = (num) => num.toString();

泛型接口与类

类可以实现泛型接口,这要求类也必须成为泛型类或者为接口的类型参数提供具体类型。这种模式在创建可重用组件时特别有用。

interface Repository<T> {
  add(item: T): void;
  get(id: number): T;
  getAll(): T[];
}

class UserRepository implements Repository<User> {
  private users: User[] = [];
  
  add(user: User): void {
    this.users.push(user);
  }
  
  get(id: number): User {
    return this.users.find(user => user.id === id)!;
  }
  
  getAll(): User[] {
    return [...this.users];
  }
}

泛型接口的约束

我们可以通过extends关键字对泛型参数添加约束,限制可以使用的类型。这确保了类型参数具有特定的属性或方法,同时仍然保持灵活性。

interface Lengthwise {
  length: number;
}

interface SizedContainer<T extends Lengthwise> {
  contents: T;
  size(): number;
}

const stringContainer: SizedContainer<string> = {
  contents: "hello",
  size() {
    return this.contents.length;
  }
};

泛型接口的默认类型

TypeScript允许为泛型参数指定默认类型,当使用接口时没有显式提供类型参数时,将使用默认类型。

interface PaginatedResponse<T = any> {
  data: T[];
  total: number;
  page: number;
  perPage: number;
}

const userResponse: PaginatedResponse<User> = {
  data: [{ id: 1, name: "Alice" }],
  total: 1,
  page: 1,
  perPage: 10
};

const anyResponse: PaginatedResponse = {
  data: [1, 2, 3],
  total: 3,
  page: 1,
  perPage: 10
};

泛型接口与索引签名

泛型接口可以与索引签名结合使用,创建灵活的字典或映射类型。这种模式在处理动态键值对时特别有用。

interface Dictionary<T> {
  [key: string]: T;
}

const numberDict: Dictionary<number> = {
  "one": 1,
  "two": 2,
  "three": 3
};

const stringDict: Dictionary<string> = {
  "en": "English",
  "es": "Spanish",
  "fr": "French"
};

泛型接口的高级用法

泛型接口可以嵌套使用,创建更复杂的类型结构。这种模式在构建大型应用程序或库时特别有价值。

interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: string;
}

interface UserProfile {
  id: number;
  name: string;
  email: string;
}

interface PaginatedApiResponse<T> extends ApiResponse<T[]> {
  page: number;
  totalPages: number;
}

const userResponse: ApiResponse<UserProfile> = {
  success: true,
  data: {
    id: 1,
    name: "John Doe",
    email: "john@example.com"
  }
};

const usersResponse: PaginatedApiResponse<UserProfile> = {
  success: true,
  data: [
    { id: 1, name: "John Doe", email: "john@example.com" },
    { id: 2, name: "Jane Smith", email: "jane@example.com" }
  ],
  page: 1,
  totalPages: 3
};

泛型接口与条件类型

在TypeScript的高级类型系统中,泛型接口可以与条件类型结合使用,根据类型参数创建不同的类型结构。

type CheckType<T> = T extends string ? "string" : "not string";

interface TypeChecker<T> {
  type: CheckType<T>;
  value: T;
}

const stringChecker: TypeChecker<string> = {
  type: "string",
  value: "hello"
};

const numberChecker: TypeChecker<number> = {
  type: "not string",
  value: 42
};

泛型接口与映射类型

映射类型可以与泛型接口结合,动态地转换现有类型的属性。这种技术在创建实用工具类型时特别有用。

interface ReadonlyWrapper<T> {
  readonly [P in keyof T]: T[P];
}

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

const readonlyUser: ReadonlyWrapper<User> = {
  id: 1,
  name: "Alice",
  email: "alice@example.com"
};

// readonlyUser.name = "Bob"; // 错误: 无法分配到 "name" ,因为它是只读属性

泛型接口在实际项目中的应用

在实际项目中,泛型接口常用于API响应处理、状态管理、数据访问层等场景。它们提供了类型安全的同时保持了代码的灵活性。

// API响应处理
interface ApiResponse<T> {
  status: number;
  data: T;
  message?: string;
}

// 状态管理
interface State<T> {
  loading: boolean;
  error: string | null;
  data: T | null;
}

// 数据访问层
interface DataAccess<T, ID> {
  create(item: T): Promise<T>;
  read(id: ID): Promise<T | null>;
  update(id: ID, item: T): Promise<boolean>;
  delete(id: ID): Promise<boolean>;
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:泛型函数定义

下一篇:泛型类

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌