You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现泛型化的打包解包函数?修复TypeScript类型错误

泛型unpack/pack函数的类型问题解答

问题背景

将原本针对string类型的unpack(解包)和pack(打包)函数改造为泛型函数后,unpack函数未出现TypeScript类型报错,但pack函数出现如下类型不兼容错误:

Type 'T | (T & ({} | null))[]' is not assignable to type 'T extends unknown[] | undefined ? T : T[]'.
Type 'T' is not assignable to type 'T extends unknown[] | undefined ? T : T[]'.

原函数代码

/**
 * Unpack an element if it is packed.
 * @param data - Data from which to unpack.
 */
export const unpack = (
  data: undefined | string | string[],
  index: number = 0,
): undefined | string => (Array.isArray(data) ? data[index] : data);

/**
 * Pack an element if it is unpacked.
 * @param data - Data to pack.
 */
export const pack = (
  data: undefined | string | string[],
): undefined | string[] =>
  Array.isArray(data) || data === undefined ? data : [data];

泛型尝试代码

/**
 * Unpack an element if it is packed.
 * @param data - Data from which to unpack.
 */
export const unpack = <T,>(
  data: T,
  index: number = 0,
): T extends unknown[] ? T[number] : T =>
  Array.isArray(data) ? data[index] : data;

/**
 * Pack an element if it is unpacked.
 * @param data - Data to pack.
 */
export const pack = <T,>(data: T): T extends unknown[] | undefined ? T : T[] =>
  Array.isArray(data) || data === undefined ? data : [data];

问题解答

1. 泛型unpack函数的类型定义是否正确?

基本符合原函数的逻辑,但有细节可以优化:

  • 类型定义能正确推导返回值:当T是数组类型时返回数组元素类型T[number],非数组类型时返回原类型T,和原函数的解包行为一致。
  • 小缺陷:如果传入空数组,data[index]会返回undefined,但当前类型定义不会体现这一点。如果需要严格对齐实际行为,可以调整条件类型处理空数组场景,但如果只是和原函数逻辑对齐,当前定义是可接受的。

2. 如何修复泛型pack函数的类型错误?

TypeScript无法自动将返回值的联合类型T | T[]与条件类型做精确匹配,推荐用函数重载解决(更符合TypeScript类型系统设计),也可以用类型断言快速修复:

方案一:函数重载(推荐)

通过明确的重载签名让TypeScript精确匹配输入输出类型:

/**
 * Pack an element if it is unpacked.
 * @param data - Data to pack.
 */
export function pack<T>(data: T[]): T[];
export function pack<T>(data: undefined): undefined;
export function pack<T>(data: T): T[];
export function pack<T>(data: T | T[] | undefined) {
  return Array.isArray(data) || data === undefined ? data : [data];
}

方案二:类型断言

如果不想用重载,可通过类型断言告诉TypeScript返回值符合定义:

/**
 * Pack an element if it is unpacked.
 * @param data - Data to pack.
 */
export const pack = <T,>(data: T): T extends unknown[] | undefined ? T : T[] =>
  (Array.isArray(data) || data === undefined ? data : [data]) as T extends unknown[] | undefined ? T : T[];

错误原因说明

pack函数报错是因为TypeScript处理条件类型时,无法提前确定T是否属于unknown[] | undefined,因此返回值的联合类型T | T[]无法被自动推导为条件类型的结果。而unpack函数之所以无报错,是因为数组场景下data[index]的类型被推断为T[number],和条件类型结果匹配度更高,TypeScript能通过类型窄化完成推断。


内容的提问来源于stack exchange,提问作者Géry Ogam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:45:03