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

TypeScript中能否在编译时判断类型并实现参数包装函数?

问题描述

我有类型A或B的实例,想要创建一个单一函数,接收A或B类型的参数,并返回对应的包装后的参数。我写了示例代码,但不确定在TypeScript中能否实现该需求:

type A = { name: string };
type B = A[];

type DucktypedA = { 
  a: A,
};

type DucktypedB = {
  b: B,
}

function test(arg: A | B): DucktypedA | DucktypedB {
  if (arg instanceof A) {
    return { a: arg };
  } else {
    return { b: arg };
  }
}

期望的调用结果:

const a = { name: "me" };
const wrappedA = test(a); // --> { a: { name: "me" } }

const b = [{ name: "me" }];
const wrappedB = test(b); // --> { b: [{ name: "me" }] }
解决方案

可以实现,但你当前代码里的arg instanceof A无法生效——因为A是TypeScript的类型别名,编译后会被完全擦除,JavaScript运行时根本不知道A的存在,自然无法用instanceof做判断。

要实现需求,需要用运行时可识别的逻辑区分A和B:由于B是A的数组类型,我们可以用Array.isArray()来判断参数是否为数组,同时结合TypeScript的类型守卫让类型推断生效。

方式一:函数重载+类型守卫

这种方式的类型推断最直观,能明确对应输入输出的类型关系:

type A = { name: string };
type B = A[];

type DucktypedA = { a: A };
type DucktypedB = { b: B };

// 函数重载:声明不同输入对应的输出类型
function test(arg: A): DucktypedA;
function test(arg: B): DucktypedB;
// 实际实现逻辑
function test(arg: A | B): DucktypedA | DucktypedB {
  if (Array.isArray(arg)) {
    return { b: arg };
  } else {
    return { a: arg };
  }
}

// 调用验证
const a = { name: "me" };
const wrappedA = test(a); // 类型自动推断为 DucktypedA
const b = [{ name: "me" }];
const wrappedB = test(b); // 类型自动推断为 DucktypedB

方式二:泛型+条件类型

如果希望函数的返回类型更动态,可以用泛型结合条件类型实现:

type A = { name: string };
type B = A[];

// 条件类型:根据输入类型自动映射包装类型
type Ducktyped<T> = T extends A ? { a: T } : { b: T };

function test<T extends A | B>(arg: T): Ducktyped<T> {
  if (Array.isArray(arg)) {
    return { b: arg } as Ducktyped<T>;
  } else {
    return { a: arg } as Ducktyped<T>;
  }
}

// 调用验证
const wrappedA = test({ name: "me" }); // 类型为 { a: { name: string } }
const wrappedB = test([{ name: "me" }]); // 类型为 { b: { name: string }[] }

两种方式都能完全满足你的需求,可根据实际场景选择使用。

内容的提问来源于stack exchange,提问作者hugotsoma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:42:52