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

TypeScript如何实现基于函数参数的条件返回类型自动推断?

问题原因

当你显式指定第一个泛型参数T时,TypeScript会默认使用第二个泛型参数S的默认值false,并不会自动从传入的opts参数中推断S的类型。这就导致你传入的single: true与S=false的类型约束冲突,从而抛出类型错误。

解决方案

这里提供两种可靠的解决方式:

方式一:调整泛型推断逻辑,让S从opts自动推断

移除S的默认值,同时处理默认参数的类型兼容性:

interface Options<S extends boolean> {
  limit?: number
  offset?: number
  single?: S
}

const fetchItems = async <T = unknown, S extends boolean>(
  collection: string,
  opts: Options<S> = { single: false } as Options<S>
): Promise<S extends true ? T : T[]> => {
  const { data } = await axios.get<{ data: any }>(`/items/${collection}`, {
    params: {
      limit: opts.limit,
      offset: opts.offset,
      single: opts.single,
    },
  })

  return data.data
}

调用示例:

// 自动推断S为true,返回Promise<{id: number}>
await fetchItems<{ id: number }>("pages", { single: true })
// 自动推断S为false,返回Promise<{id: number}[]>
await fetchItems<{ id: number }>("pages")

方式二:使用函数重载(更直观的类型约束)

通过重载函数直接定义不同参数对应的返回类型,避免泛型推断冲突:

interface Options<S extends boolean> {
  limit?: number
  offset?: number
  single?: S
}

// 重载1:传入single: true时,返回单个T类型
async function fetchItems<T>(collection: string, opts: Options<true>): Promise<T>
// 重载2:不传opts或传入single: false时,返回T数组
async function fetchItems<T>(collection: string, opts?: Options<false>): Promise<T[]>

// 通用实现
async function fetchItems<T>(
  collection: string,
  opts: Options<boolean> = {}
): Promise<T | T[]> {
  const { data } = await axios.get<{ data: any }>(`/items/${collection}`, {
    params: {
      limit: opts.limit,
      offset: opts.offset,
      single: opts.single,
    },
  })

  return data.data
}

调用示例:

// 返回Promise<{id: number}>
await fetchItems<{ id: number }>("pages", { single: true })
// 返回Promise<{id: number}[]>
await fetchItems<{ id: number }>("pages")

两种方式都能解决你的类型错误问题,其中函数重载的方式类型提示更清晰,适合需要明确区分返回类型的场景。

内容的提问来源于stack exchange,提问作者Mattia D.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:13:09