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

非泛型函数的泛型工厂:TypeScript替代Parameters类型方案

替代Parameters工具类型实现TypeScript函数参数约束

原始代码示例

const graphql = {
    query: function<A, B>(x: string, y: (a: A, b: B) => void) {
        return x;
    }
}

function makeOverride<Q, V>(queryName: string) {
  return (fn: Parameters<typeof graphql.query<Q, V>>[1]) => graphql.query<Q, V>(queryName, fn)
}

const bound = makeOverride<string, boolean>('some')
const bound2 = makeOverride<number, 'cow' | 'dog'>('some')

// 正常工作
bound((x: string, y: boolean) => {})
bound2((x: number, y: 'cow' | 'dog') => {})

替代实现方案

以下几种方法都可以在不使用Parameters工具类型的前提下,确保传入makeOverride<A, B>("")(fn)的fn符合(x: A, b: B) => void的约束:

方案1:显式定义回调类型别名

把原函数的回调类型抽成独立别名,让原函数和工厂函数复用这个类型,避免重复定义:

// 提取回调类型为独立别名
type QueryCallback<A, B> = (a: A, b: B) => void;

const graphql = {
    query: function<A, B>(x: string, y: QueryCallback<A, B>) {
        return x;
    }
}

function makeOverride<Q, V>(queryName: string) {
  return (fn: QueryCallback<Q, V>) => graphql.query<Q, V>(queryName, fn)
}

方案2:直接匹配原函数的泛型签名

直接在工厂函数的返回值里,写出和原函数完全一致的回调签名,对应上泛型参数即可:

const graphql = {
    query: function<A, B>(x: string, y: (a: A, b: B) => void) {
        return x;
    }
}

function makeOverride<Q, V>(queryName: string) {
  return (fn: (a: Q, b: V) => void) => graphql.query<Q, V>(queryName, fn)
}

方案3:提取原函数类型复用

先提取外部库函数的完整类型,再基于该类型复用回调约束,适合类型复杂的外部库场景:

const graphql = {
    query: function<A, B>(x: string, y: (a: A, b: B) => void) {
        return x;
    }
}

// 提取原函数的类型
type QueryFunction = typeof graphql.query;

// 基于原函数类型定义回调类型(无需Parameters)
type QueryCallback<A, B> = (a: A, b: B) => void;

function makeOverride<Q, V>(queryName: string) {
  return (fn: QueryCallback<Q, V>) => graphql.query<Q, V>(queryName, fn)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 01:17:26