TypeScript 泛型 T 详细解释

news/2025/10/1 0:01:06/文章来源: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.mzph.cn/news/923372.shtml

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

相关文章

网站建设夬金手指花总wordpress 国际支付宝

需求实现支付宝类似的效果&#xff1a; 思路&#xff1a; 1.首先建立展开收起按钮&#xff0c;这里使用的是uview里面的icon图标。 2.其次建立展开菜单内容&#xff0c;这里只演示了文本信息&#xff0c;后期引入首页应用。 3.最后写js逻辑&#xff0c;展开收起时改变盒子高度和…

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

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

网站建设企业开发公司跨境进口网站怎么做

axios本身是没有同步请求的&#xff0c;要实现同步请求&#xff0c;用到的是ES7的async和await ES7的异步特性async / await async用于声明一个函数是异步的&#xff0c;await用于声明在一个异步函数中等待语句执行完毕。也就是说await只能在async函数中使用。简单示例如下&a…

网上销售 网站建设2020网页游戏

1.简介 Fiddler是一款强大的HTTP抓包工具&#xff0c;它能记录所有客户端和服务器的http和https请求&#xff0c;允许你监视&#xff0c;设置断点&#xff0c;甚至修改输入输出数据. 使用Fiddler无论对开发还是测试来说&#xff0c;都有很大的帮助。Fiddler提供的功能基本上能…

2025秋_6

今天学习了java

程序语言杂谈:C/C++

谈谈 C/C++ 的优劣C C++问世时间、创始公司 1972,Bell Laboratory 1979,Bell LaboratoryOOP 能力 不支持 强大,但复杂类型系统 强类型 强类型运行模式 原生编译 原生编译跨平台能力 一般 一般性能 极高 极高关键词 …

2025秋_7

今天学习了java

PEP8 规范

PEP8 是 Python 官方推荐的代码风格指南,旨在提高代码的可读性和一致性。 官方文档:https://legacy.python.org/dev/peps/pep-0008/ 中文翻译文档:https://blog.csdn.net/ratsniper/article/details/78954852 缩进与…

Pycharm 设置

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

9.9网站怎么做wordpress文件上传函数

大家好,今日继续给大家讲解VBA数据库解决方案的第21讲,如何利用VBA代码在已有的数据表中删除&#xff0c;添加&#xff0c;修改字段。这个内容是操作数据库的一项必修的内容&#xff0c;还望大家在实际工作中多利用&#xff0c;所以这节的知识&#xff0c;对于读者提高自己的数…

[NOIP 2016 提高组] 组合数问题

我们先考虑暴力,暴力枚举每一个\(i,j\)暴力算\(\binom{i}{j}\) 时间复杂度为\(O(T*N^3)\),显然超时 然后我们发现\(N,M \le2000\) 我们考虑使用组合数的递推公式预处理\(\binom{0}{0}\)到\(\binom{2000}{2000}\)。 这…

学校网站建设需求分析做响应式网站最大宽度

实现: 1) cImage:抽象类; cImageReal:派生类, 不可直接实例化; cImageProxy:派生代理类, 可直接实例化用来代理cImageReal; NOTICE:派生代理类用来简化对特定派生类的使用. 使用: 实例化代理类, 然后使用. 1) 设计框架 /*image.hpp*/ #pragma once #…

网站后台上传文章用php做网站后台

一只小猴子一天摘了许多桃子&#xff0c;第一天吃了一半&#xff0c;然后忍不住又吃了一个&#xff1b;第二天又吃了一半&#xff0c;再加上一个&#xff1b;后面每天都是这样吃。到第10天的时候&#xff0c;小猴子发现只有一个桃子了。问小猴子第一天共摘了多少个桃子。 实例…

镇江建设工程质量监督局网站简述基于构件的软件开发流程

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 情景描述&#xff1a;只是想简单写个 ActiveMQ 的小样&#xff0c;启动服务却报错&#xff1a; Error starting ApplicationContext…

工作站做网站使用oss做静态网站

0. 引言 在生产中我们要尽可能避免单点故障&#xff0c;nginx也不例外&#xff0c;因此搭建主备节点必不可少&#xff0c;今天我们来学习下如何利用keepalived实现主备 1. keepalived简介 keepalived 是一个LINUX系统中开源的负载均衡和故障转移软件&#xff0c;它主要用于高…

新建第一个项目

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

企业网站设计与制作婚礼效果图网站

前面的文章我们曾介绍过皮尔磁(Pilz)的安全继电器PNOZ X3和X2.7P/2.8P &#xff0c;(参考&#xff1a;如何使用Pilz的安全继电器PNOZ X2.7P/X2.8P&#xff1f;)今天这篇文章&#xff0c;我们来介绍另外一款安全继电器产品PNOZ s4.PNOZ s4可以用于急停按钮、安全门、安全开关等场…

笛卡尔树 (区间最小值)

笛卡尔树 (区间最小值)https://codeforces.com/gym/105588/problem/M #include<bits/stdc++.h> using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); #…

CF2003F. Turtle and Three Sequences

给你三个长为 \(n\) 的序列 \(a,b,c\)。 求所有满足一下条件的 \([1,2,\cdots,n]\) 的长为 \(m\) 的子序列 \(p_1,p_2,\cdots,p_m\) 中,\(\sum_{i=1}^m c_{p_i}\) 的最大值\(a_{p_1}\le a_{p_2}\le\cdots\le a_{p_m}\…

网站 空间 购买企业年报系统官网

前言 etcd是线性一致性读&#xff0c;而zk却是顺序一致性读&#xff0c;再加上各种共识、强弱一致的名词&#xff0c;看到欸度时候总会混淆&#xff0c;这里会给出一些例子来帮助理解。 什么是一致性&#xff1f; 在谈到一致性这个词时&#xff0c;你会想到CAP理论的consist…