TypeScript 泛型 T 详细解释

news/2025/11/16 14:45:26/文章来源:https://www.cnblogs.com/bingquan1/p/19121955

什么是泛型

  • T 是一个类型变量,代表"某种类型"

举个例子

  • loadMore: (page: number) => Promise<T[]>;
  • 相当于说:这个函数返回一个Promise,Promise解析的结果是T类型的数组

实际使用时的具体化

// 当 T = Product 时:
loadMore: (page: number) => Promise<Product[]>;// 当 T = string 时:
loadMore: (page: number) => Promise<string[]>;// 当 T = User 时:
loadMore: (page: number) => Promise<User[]>;

在组件中的完整应用

// 定义泛型组件
interface InfiniteScrollProps<T = any> {loadMore: (page: number) => Promise<T[]>;  // T 在这里定义renderItem: (item: T, index: number) => React.ReactNode;  // 这里也用 T
}// 使用泛型组件时,T 会被具体类型替换
function ProductList() {return (<InfiniteScroll<Product>  // 这里明确指定 T = ProductloadMore={fetchProducts}  // 现在这个函数需要返回 Promise<Product[]>renderItem={(product) => (  // 这里的 product 自动就是 Product 类型<div>{product.name} - ${product.price}</div>)}/>);
}

举个例子

用户数据

// 定义用户类型
interface User {id: number;name: string;email: string;avatar: string;
}function UserList() {// 加载用户数据的函数 - 必须返回 User[]const loadUsers = async (page: number): Promise<User[]> => {const response = await fetch(`/api/users?page=${page}`);const data = await response.json();return data.users; // 这里必须是 User[] 类型};// 渲染用户项 - item 自动推断为 User 类型const renderUser = (user: User) => (<div className="user-card"><img src={user.avatar} alt={user.name} /><h3>{user.name}</h3><p>{user.email}</p></div>);return (<InfiniteScroll<User>  // 明确指定类型loadMore={loadUsers}renderItem={renderUser}/>);
}

文章数据

// 定义文章类型
interface Article {id: string;title: string;content: string;author: string;createdAt: Date;
}function ArticleList() {const loadArticles = async (page: number): Promise<Article[]> => {const response = await fetch(`/api/articles?page=${page}`);return response.json(); // 返回 Article[]};const renderArticle = (article: Article) => (<article><h2>{article.title}</h2><p>By {article.author}</p><div>{article.content}</div></article>);return (<InfiniteScroll<Article>loadMore={loadArticles}renderItem={renderArticle}/>);
}

类型自动推断

  • 如果不显式指定 ,TypeScript 会尝试自动推断:
function Example() {// TypeScript 会根据 loadMore 的返回值推断 T = Productconst loadMore = async (page: number): Promise<Product[]> => {// ...};// 这里不需要显式写 <Product>return (<InfiniteScrollloadMore={loadMore}  // TypeScript 知道这里 T = ProductrenderItem={(product) => {  // product 自动就是 Product 类型product.id;    // ✅ 正确product.name;  // ✅ 正确  product.abc;   // ❌ 错误:Product 类型没有 abc 属性}}/>);
}

泛型的优势

类型安全

interface Product {id: number;name: string;price: number;
}// 如果 loadMore 返回了错误类型,TypeScript 会报错
const loadMore = async (page: number): Promise<Product[]> => {return [{ id: 1, name: "Phone", price: 999 },{ id: 2, name: "Tablet", price: 699 },{ id: 3, name: "Laptop" } // ❌ 错误:缺少 price 属性];
};

智能提示

const renderItem = (product: Product) => {// 编辑器会提供 Product 的所有属性提示:product. // 输入 . 后会提示:id, name, price
};

复杂类型示例

嵌套对象

interface Post {id: number;title: string;author: {id: number;name: string;avatar: string;};tags: string[];
}function PostList() {const loadMore = async (page: number): Promise<Post[]> => {// 必须返回 Post[] 类型};const renderItem = (post: Post) => (<div><h3>{post.title}</h3><img src={post.author.avatar} alt={post.author.name} /><div>{post.tags.map(tag => (<span key={tag}>{tag}</span>))}</div></div>);return (<InfiniteScroll<Post>loadMore={loadMore}renderItem={renderItem}/>);
}

默认类型

  • 在类型定义中,我们可以给泛型一个默认类型:
// T = any 表示如果不指定类型,就使用 any
interface InfiniteScrollProps<T = any> {loadMore: (page: number) => Promise<T[]>;renderItem: (item: T, index: number) => React.ReactNode;
}// 这样使用时,T 就是 any 类型(不推荐,失去类型安全)
function AnyList() {return (<InfiniteScroll  // 没有指定 <T>loadMore={async (page) => [{ anything: 'here' }]}  // 返回 any[]renderItem={(item) => (<div>{item.anything}     // ✅ 不会报错,但也没有类型提示{item.something}    // ✅ 也不会报错</div>)}/>);
}

总结

  • 是 TypeScript 的泛型参数,代表"某种类型"
  • T[] 表示"T类型的数组"
  • Promise<T[]> 表示"异步返回T类型数组的Promise"
  • 使用泛型让组件类型安全且灵活
  • 在实际使用时,T 会被具体的类型(如 Product, User 等)替换
  • 这样设计的好处是:一次编写,多种类型复用,同时保持完整的类型检查和智能提示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/169869.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Rust GUI开发入门】编写一个本地音乐播放器(12. 国际化应用-多语言支持) - Jordan

本系列教程对应的代码已开源在 Github zeedle 本篇文章介绍Slint UI如何为播放器页面添加多语言支持,让你的应用走向国际!Translations | Slint Docs1. 使用@tr修饰.slint中的字面量 就像这样:2. 提取要翻译的字符串…

Pycharm 设置

使用新老 UI修改注释样式Block comment:修改多行注释的字体颜色 Doc Comment –> Text:修改文档注释的字体颜色 Line comment:修改单行注释的字体颜色

新建第一个项目

点击 New Project:为项目进行配置:这是项目的虚拟环境,里面的文件不能修改:新建文件夹:给文件夹命名:新建 Python 文件:给文件命名:

US$11 High Quality LED BDM Frame Clip Cable

High Quality LED BDM Frame Clip CableWorks together with LED BDM Frame,So if your original LED BDM Frame Clip cable is lost or damaged,you could order this alone, it is made by High Quality .Package in…

【Rust GUI开发入门】编写一个本地音乐播放器(11. 支持动态明暗主题切换) - Jordan

本系列教程对应的代码已开源在 Github zeedle暗色主题 亮色主题Slint UI内置全局调色板,支持运行时动态切换明暗主题,这通过更改Palette.color-scheme来实现:Palette.color-scheme = ColorScheme.light变为亮色主题…

利用接口中的静态虚拟成员实现自定义配置节

本文介绍了C# 11中静态虚拟成员接口的新特性,展示了如何利用这一特性简化自定义配置节的注册和使用过程。通过定义IConfigOptions接口和扩展方法,实现了类型安全的配置管理,减少了重复代码。利用接口中的静态虚拟成…

天线增益与有源接收面积之间的关系

最近在看卫星通信,在学习星地链路传输的时候看到以下内容对于频率低于 1 GHz 的频段,使用有源接收面积接收电波时效率提升很困难 频率较低时,波长较长,小口径天线有效接收面积(有效口径)反而较小 有源接收面积 \…

US$54 AM29FXXX Adapter for CG Pro 9S12 Programmer

AM29FXXX Adapter for CG Pro 9S12 ProgrammerAM29FXXX Adapter is used to do AM29F200/AM29F400/AM29F800 series chip for ECU repair, Immobilizer repair etc.If your CG Pro 9S12 is with new design, please ch…

流量分析

流量分析 主要还是对近期遇到的流量题目做一个总结,重在思路总结,方便以后翻阅@_@ 题目:[第九章][9.3.2 webshell混淆流量分析]webshell流量分析 NetA一把梭手搓 wireshark,筛选http->按包的长度(length)排序…

RPC在分布式存储系统中的应用 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

US$134 Tango Toyota Key Maker Authorization Service

Tango Toyota Key Maker Authorization ServiceIf you buy Tango Key Programmer Basic Software (SK80), and want to get the Toyota Key Maker Authorization, you can buy this service.Tips: No need shipping, a…

实用指南:矩阵结构体 图片绘制 超级玛丽demo6

实用指南:矩阵结构体 图片绘制 超级玛丽demo6pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &q…

C语言实战任务:贪吃蛇(2)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

阿里云函数计算 AgentRun 全新发布,构筑智能体时代的基础设施 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【Rust GUI开发入门】编写一个本地音乐播放器(10. 拼装UI组件) - Jordan

本系列教程对应的代码已开源在 Github zeedle 将前文写的零散的UI组件(歌曲列表/播放控制面板/歌词面板/设置面板)拼装起来,组成最终的音乐播放器UI,用TabWidget分成多标签页,每一个标签页分担不同的功能:export…

破解 Pycharm

破解 Pycharm破解工具:下载链接: https://pan.baidu.com/s/1C4BB55LXPxW4s9lZlFt4FA?pwd=s5jc 提取码: s5jc 破解完成后,这个目录依然不能删除,否则破解失效。所以可将该目录保存至一个很少打开的位置。 先执行…

CAP 8.4 版本发布通告

前言 今天,我们很高兴宣布 CAP 发布 8.4 版本正式版。从 8.3.0 版本以来,我们陆续发布了 5 个小版本,在这些版本中我们主要专注于提升系统性能、增强 Dashboard 功能、改进存储提供程序支持,并修复了一系列已知问题…

STM32 智能垃圾桶项目笔记(一):超声波模块(HC-SR04)原理与驱动实现 - 教程

STM32 智能垃圾桶项目笔记(一):超声波模块(HC-SR04)原理与驱动实现 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-f…

DevEco Studio 编辑器的使用 - 实践

DevEco Studio 编辑器的使用 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco…

【Rust GUI开发入门】编写一个本地音乐播放器(9. 制作设置面板) - Jordan

本系列教程对应的代码已开源在 Github zeedle 目的是制作这样的一个简单设置面板,里面有一些简单设置项,居中在屏幕中央:即,每个设置项之间竖直方向布局,然后设置项内部,文字和控件水平布局: export component …