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

如何在TypeScript中从函数返回类型排除特定类型?

解决TypeScript中排除函数返回特定类型的问题

想要定义函数类型,限制其返回值不能是Promise、Observable这类包装类型,仅允许返回普通的Record<string, any>对象。尝试了以下写法但无法生效:

type FooFn = {
    <T extends Record<string, any>>(): T extends Promise<any> ? never : T;
};

const foo: FooFn = () => ({ 'ok': 'ok' }); // 期望正常工作
const foo2: FooFn = () => { return Promise.resolve({ 'ok': 'ok' }) }; // 期望报错但实际没有

补充说明:实际需求是要定义两种函数类型,其中Fn不允许返回Promise等异步包装类型,AsyncFn则明确返回Promise包裹的对象:

type Fn = () => Record<string, any>; // 期望不允许返回Promises、Observables等
type AsyncFn = () => Promise<Record<string, any>>;

const foo: Fn = () => ({ 'ok': 'ok' }); // 期望正常工作
const foo2: Fn = () => { return Promise.resolve({ 'ok': 'ok' }) }; // 期望报错但实际没有

问题原因

原写法使用泛型条件类型时,TypeScript的类型推断逻辑会让T匹配返回值的实际类型。当返回Promise时,T被推断为Promise<{ok: string}>,此时条件类型返回never。但TypeScript允许任何返回值类型的函数赋值给返回never的函数类型(因为never是所有类型的子类型),所以不会触发预期的错误。

正确实现方式

通过条件类型直接约束函数的返回值,让被禁止的返回类型解析为never,利用TypeScript的赋值兼容性检查触发错误:

// 定义需要排除的返回类型集合
type ForbiddenTypes = Promise<any>; // 可添加 Observable<any> 等其他需要排除的类型

// 定义Fn类型:返回值必须是符合Record<string, any>且不属于禁止类型的类型
type Fn = () => Record<string, any> extends infer T 
  ? T extends ForbiddenTypes 
    ? never 
    : T 
  : never;

type AsyncFn = () => Promise<Record<string, any>>;

// 测试用例
const foo: Fn = () => ({ 'ok': 'ok' }); // ✅ 正常通过
const foo2: Fn = () => Promise.resolve({ 'ok': 'ok' }); // ❌ 报错:类型“Promise<{ ok: string; }>”不能赋值给类型“never”

也可以拆分出辅助类型让代码更清晰:

type ForbiddenTypes = Promise<any> | Observable<any>;
type AllowedReturn<T> = T extends ForbiddenTypes ? never : T;

type Fn = () => AllowedReturn<Record<string, any>>;
type AsyncFn = () => Promise<Record<string, any>>;

这样实现后,只要函数返回ForbiddenTypes中包含的类型,就会触发类型错误,符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:35:23