TypeScript泛型函数如何根据传入类型参数执行不同逻辑
问题核心原因
TypeScript 的类型系统仅在编译阶段生效,编译为 JavaScript 后所有泛型参数、类型标注都会被完全擦除,运行时不存在Type这个可访问的值,因此你写的if (Type == number)这类伪代码无法直接实现,所有类型分支判断必须基于运行时可获取的值来完成。
实现方案
方案1:基于数组元素的运行时类型判断(最常用)
因为入参v是Type[]类型,当你传入f<number>([1,2])时,数组元素都是number类型;传入f<string>(["a","b"])时元素都是string类型,直接检测数组元素的类型即可触发TS的类型收窄,同时执行对应分支逻辑。
注意需要先处理空数组的边界场景:
type Foo = number | string function f<Type extends Foo>(v: Type[]) { // 空数组无法通过元素判断类型,可根据业务需求处理 if (v.length === 0) { throw new Error("空数组无法判定元素类型") } const firstEl = v[0] if (typeof firstEl === "number") { // 此分支下TS会自动将类型收窄为number[],可直接执行数字相关逻辑 const numList = v as number[] console.log("执行number分支:数组求和结果为", numList.reduce((sum, cur) => sum + cur, 0)) return } if (typeof firstEl === "string") { // 此分支下TS会自动将类型收窄为string[],可直接执行字符串相关逻辑 const strList = v as string[] console.log("执行string分支:数组拼接结果为", strList.join("-")) return } } // 测试调用 f<number>([1, 2]) // 执行number分支:数组求和结果为 3 f<string>(["hello", "world"]) // 执行string分支:数组拼接结果为 hello-world
注意:该方案要求传入的数组元素类型统一,如果传入
[1, "test"]这类同时包含number和string的混合数组(本身也符合Foo[]的类型约束),会出现判断偏差。如果要规避这个问题,可以在判断分支前先遍历全数组校验所有元素类型一致。
方案2:传入显式类型标记(适配空数组等特殊场景)
如果业务中存在传入空数组的需求,无法通过元素判断类型,可以额外增加一个运行时可访问的类型标记参数,通过标记判断分支,完全不依赖数组内容:
type Foo = number | string type TypeFlag = "number" | "string" function f<Type extends Foo>(flag: TypeFlag, v: Type[]) { switch(flag) { case "number": const numList = v as number[] console.log("执行number分支逻辑") break case "string": const strList = v as string[] console.log("执行string分支逻辑") break } } // 调用时显式传入类型标记,空数组也能正确走对应分支 f<number>("number", [1,2]) f<string>("string", [])
内容的提问来源于stack exchange,提问作者Guid
相关产品推荐
相关产品推荐

