一文彻底搞明白HarmonyOS基础TypeScript中的泛型函数

简介: 程序员Feri是一位拥有12年+经验的技术专家,擅长嵌入式、鸿蒙、人工智能和Java等领域。本文深入探讨TypeScript中的泛型函数,涵盖基础语法、类型约束、高级技巧及应用场景。通过泛型函数,实现代码逻辑与具体类型的解耦,提升类型安全性和复用性。内容包括集合操作、API抽象、工具类开发等实际应用,以及条件类型、默认类型参数和工具类型的高级技巧。最后提醒开发者注意过度泛型化和性能权衡问题,总结泛型函数在TypeScript类型系统中的核心地位及其未来发展方向。

程序员Feri一名12年+的程序员,做过开发带过团队创过业,擅长嵌入式、鸿蒙、人工智能、Java等,专注于程序员成长那点儿事,希望在成长的路上有我相伴!君志所向,一往无前!





最近在写HarmonyOS NEXT项目中发现,还是需要对于TypeScript的语法进行掌握了解,特别是灵活使用ArkTS的应用的时候,所以就来了篇关于TypeScript的。


1.泛型函数


泛型函数是 TypeScript 类型系统的核心抽象工具,其设计遵循参数化多态(Parametric Polymorphism)原则,通过将类型作为参数传递,实现代码逻辑与具体类型的解耦。



这种机制突破传统静态类型语言的刚性约束,赋予以下能力:



  1. 类型动态化:在保证类型安全的前提下,允许函数逻辑适配多种数据类型(如数字、字符串、对象等),避免为每种类型重写相似代码。
  2. 类型关联维护:通过泛型参数建立输入与输出、参数间的类型关联,防止类型信息在丢失(如 any 的滥用)。
  3. 约束驱动开发:通过类型约束(Type Constraints)明确定义泛型参数的合法范围,在编译阶段拦截无效操作,降低运行时风险。




2.泛型函数的语法


2.1 基础语法结构


泛型函数通过 <T> 声明类型参数,参数可出现在函数参数、返回值及内部逻辑中:


function reverse<T>(items: T[]): T[] {
  
    return [...items].reverse();
}


  • 类型参数化<T> 声明类型占位符,调用时由传入参数类型动态绑定。


  • 自动类型推断:编译器通过参数类型自动推导 T 的具体类型(如 reverse([1,2,3]) 推导为 number[]),减少显式标注需求。


  • 多参数泛型:支持多个独立类型参数(如 <T, U>),处理复杂类型交互:


    function zip<TU>(arr1: T[], arr2: U[]): [TU][] {
        
        return arr1.map((item, i) => [item, arr2[i]]);
    }


2.2 类型推导的原理


TypeScript 采用双向类型推断算法,结合上下文类型(Contextual Typing)与参数类型推导泛型实例化:



  1. 正向推导:根据传入参数类型确定泛型参数(如 map([1,2], n => n+1) 推导 T=number, U=number)。


  2. 反向推导:通过返回值类型反向约束泛型参数(常见于高阶函数或 Promise 链式调用)。


  3. 约束优先级:显式类型标注(如 reverse<string>(["a","b"]))优先于自动推导。





3.泛型类型约束与实践


3.1 基础类型约束(extends


通过 T extends Constraint 限制泛型参数的合法范围:


interface HasLength { length; }

function logSize<T extends HasLength>(obj: T): void {
    console.log(obj.length); // 安全访问约束属性
}


  • 属性约束:确保泛型参数具备特定属性(如 length),避免运行时属性缺失错误。


  • 类型联合约束:支持联合类型约束(如 T extends number | string),扩展泛型适用范围。



3.2 高级约束技巧



  1. 泛型函数类型约束


    function invokeWithLog<T extends (...args: any[]) => any>(fn: T): ReturnType<T{
        
        console.log(Calling&nbsp;<span class="hljs-subst">${fn.name}</span>);
        return fn();
    }

  2. 递归约束:处理嵌套数据结构时,通过递归类型定义约束(如树形结构遍历):


    interface TreeNode<T> { value: T; children: TreeNode<T>[]; }
    function walkTree<T>(node: TreeNode<T>, callback: (val: T) => void/ ... / }




4.泛型函数的应用场景


4.1 集合操作与数据转换


泛型函数天然适用于数组、集合类操作,保持元素类型一致性:


function filterByKey<TK extends keyof T>(items: T[], key: K, value: T[K]): T[] {
  
    return items.filter(item => item[key] === value);
}

// 使用示例
const users = [{ id: 1, name: "Feri" }, { id: 2, name: "关注我" }];
filterByKey(users, "id"1); 
// 返回 [{ id: 1, name: "Feri" }]

4.2 API 抽象


构建通用 API 客户端时,泛型确保请求/响应类型严格匹配:


interface Api> {
  
    status: number;
    data: T;
    timestamp: Date;
}

async function fetchData<T>(url: string): Promise<ApiResponse<T>> {
    const response = await fetch(url);
    return response.json();
}
// 使用示例
interface User { id: number; name: string; }
const userData = await fetchData<User>("/api/users/1"); 
// data 类型为 User

4.3 工具类与组件开发


设计可复用工具类时,泛型提升组件通用性:


class Cache<T> {
  
    private data: Map<string, T> = new Map();
    set(key: string, value: T): void { this.data.set(key, value); }
    get(key: string): T | undefined { return this.data.get(key); }
}
// 使用示例
const userCache = new Cache<User>();
userCache.set("user1", { id: 1, name: "Alice" });



5.高级开发技巧


5.1 条件类型(Conditional Types)


结合 extends 与三元表达式实现动态类型分支:


type NonNullable<T> = T extends null | undefined ? never : T;
function safeAccess<T>(obj: T): NonNullable<T{
    if (obj == nullthrow new Error("Null value");
    return obj as NonNullable<T>;
}

5.2 默认类型参数


为泛型参数提供默认值,简化调用语法:


interface Pagination<T = string> {
  
    current: number;
    pageSize: number;
    data: T[];
}
const stringPagination: Pagination = { / 默认 T=string / };
const numberPagination: Pagination<number> = { / 显式指定 T=number / };

5.3 工具类型(Utility Types)


利用内置工具类型(如 PartialPick)增强泛型函数表现力:


function updateEntity<T>(id: string, changes: Partial<T>): void {
  
    // 应用部分更新逻辑
}
// 使用示例
interface Product { id: string; price: number; }
updateEntity<Product>("p1", { price: 99 }); // 仅更新 price 字段



6.开发注意事项与性能权衡



  1. 避免过度泛型化:过度抽象会降低代码可读性,仅在类型关系明确时使用泛型。


  2. 类型实例化深度:深层嵌套泛型可能导致编译器性能下降,需控制类型复杂度。


  3. 类型兼容性陷阱:泛型约束不匹配时可能引发隐式 any,建议开启 strictFunctionTypes 选项。





7.总结


泛型函数作为 TypeScript 类型系统的核心支柱,已在大型项目中验证其价值。


随着 TypeScript 版本迭代,可变元组类型(Variadic Tuple Types)模板字面量类型(Template Literal Types) 等新特性将进一步扩展泛型能力边界。开发者应持续关注以下方向:



  • 类型级编程:利用条件类型、映射类型构建复杂类型逻辑。
  • 泛型与函数式编程融合:结合高阶函数、柯里化实现类型安全的功能组合。
  • 性能优化:通过编译器优化减少泛型实例化开销,提升大型项目构建效率。


好啦,本篇就到这里啦,希望大家继续坚持学习!



相关文章
|
2月前
|
开发者
HarmonyOS NEXT - @Builder自定义构建函数
ArkUI 提供了轻量级的 UI 元素复用机制 `@Builder`,用于将重复使用的 UI 元素抽象为可复用组件。它支持两种使用方式:**私有自定义构建函数**和**全局自定义构建函数**。 - **私有构建函数**定义在组件内部,可访问组件状态变量,适用于需要与组件状态交互的场景。 - **全局构建函数**独立于组件,适合无状态变化的复用逻辑。 通过 `@Builder`,开发者可以简化代码结构,提高复用性和可维护性。例如,`this.task(&#39;晨跑&#39;, true)` 可动态生成任务项。参数传递支持按值和按引用两种方式,需遵循类型一致及不可修改参数值等规则。
96 13
|
2月前
|
JavaScript 开发者
HarmonyOS NEXT函数和自定义构建函数
本内容分为两部分:第一部分介绍了TypeScript中的函数用法,包括有名函数、匿名函数(lambda表达式)、类型检查、可选参数和剩余参数等特性,并通过代码示例展示了其功能与限制。第二部分讲解了ArkUI框架中的自定义构建函数(@Builder),说明了其作为轻量级UI复用机制的作用,支持私有和全局两种定义方式,并详细描述了参数传递规则,包括按值传递和按引用传递的条件及约束。
85 12
|
8月前
|
JavaScript
typeScript基础(3)_ts函数默认值和可选参数
本文介绍了在TypeScript中如何使用函数的默认值和可选参数。展示了如何为函数参数指定默认值,使得在调用函数时可以省略某些参数,以及如何定义可选参数。
455 2
|
5月前
|
索引 API
鸿蒙开发:ForEach中为什么键值生成函数很重要
在列表组件使用的时候,如List、Grid、WaterFlow等,循环渲染时都会使用到ForEach或者LazyForEach,当然了,也有单独使用的场景,如下,一个很简单的列表组件使用,这种使用方式,在官方的很多案例中也多次出现,相信在实际的开发中多多少少也会存在。
142 8
鸿蒙开发:ForEach中为什么键值生成函数很重要
|
8月前
|
JavaScript 编译器
typescript之泛型
typescript之泛型
166 60
|
6月前
|
Dart 开发者
flutter_鸿蒙next_Dart基础③函数
本文深入探讨了 Dart 编程语言中的函数概念,包括函数的基本定义、参数、返回值以及高级使用场景。通过 Flutter 和鸿蒙的实际案例,介绍了函数的定义、调用、可选参数、命名参数、匿名函数和高阶函数等内容,帮助读者更好地理解和应用 Dart 函数。
186 1
|
7月前
|
JavaScript 前端开发
TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第11天】TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
8月前
|
JavaScript 安全
typeScript进阶(14)_泛型和注意事项
TypeScript中的泛型允许创建可重用的代码。泛型可以定义函数、接口、类,支持传递类型参数,实现类型安全。泛型可以用于数组,约束类型参数必须符合特定的接口,也可以在接口和类中使用。泛型类可以包含多个类型参数,甚至在泛型约束中使用类型参数。
72 1
typeScript进阶(14)_泛型和注意事项
|
7月前
|
移动开发 JavaScript 前端开发
TypeScript:数组类型&函数使用&内置对象
本文介绍了 TypeScript 中的数组类型、对象数组、二维数组、函数、函数重载、内置对象等概念,并通过代码示例详细展示了它们的使用方法。还提供了一个使用 HTML5 Canvas 实现的下雨效果的小案例。
142 1
|
7月前
|
JavaScript 安全 前端开发
TypeScript :枚举&字符&泛型
本文介绍了 TypeScript 中的泛型、约束、枚举和字符操作的基本用法。通过示例代码展示了如何定义和使用泛型函数、类和接口,以及如何利用 `keyof` 约束类型。此外,还介绍了枚举的定义和使用,包括常量枚举和外部枚举的区别。最后,简要说明了 `?.` 和 `??` 操作符的用途,帮助处理可能为空的属性和提供默认值。