如何使用typescript中的泛型创建返回具有类型推断的函数的函数

xyhw6mcr  于 2023-06-07  发布在  TypeScript
关注(0)|答案(1)|浏览(139)

假设我想运行generateFunction(),它将返回这个函数:

// This is the returned function
const suppliedFunction = <T>(args: T) => {
    return true;
}; // This is the returned function

// so I can use it like this
suppliedFunction({ prop: "value" });

我决定像这样创建generatorFunction:

// Function generator, returning supplied function from the parameter
// The supplied function should returning a boolean
function generateFunction(fn: <T>(args: T) => boolean) {
    return fn;
}

// But this code gives me an error
// Property 'prop' does not exist on type 'unknown'
const resultFunction = generateFunction(({ prop }) => {
    return true;
});

我的目标是我可以使用resultFunction基于生成的函数进行类型推断(而不是通过显式地编写类型

// This should gives an error
// Argument of type 'string' is not assignable to parameter of type '{ prop: any; }'
resultFunction('text');

// This should be OK
resultFunction({ prop: "winter" });

对于我的情况,我们如何真正实现这个泛型?Thakks提前

uqjltbpv

uqjltbpv1#

实际上,我刚刚找到了我想要的,经过3天的解决,感谢来自这个post answer的@jcalz,我可以使用基于泛型的自定义ArgumentTypes和自定义ReturnTypes。不知何故,使用Typescript中的Parameters<>和ReturnType<>实用程序对我的项目不起作用,所以我决定使用该答案提供的自定义实用程序,然后我做了这个

type Serializables =
    | Function
    | PropertyDescriptor
    | Document
    | Omit<RegExp, "lastIndex">
    | never;

type SerializableParam<Serializable> = Serializable extends Serializables
    ? unknown
    : Serializable;

type SerializableReturnType<Serializable> =
    Serializable extends Serializables | void ? never : Serializable;

type ArgumentTypes<F extends Function> = F extends (...args: infer A) => any
    ? A
    : never;

type ReturnType<F extends Function> = F extends (...args: any) => infer A
    ? A
    : never;

interface SupplierFunction<T, Payload> extends Function {
    (arg0?): Payload extends undefined
        ? never
        : SerializableReturnType<ReturnType<T & Function>>;
    (arg0: SerializableParam<Payload>): SerializableReturnType<
        ReturnType<T & Function>
    >;
    (...arg0: SerializableParam<Payload>[]): Payload extends undefined
        ? never
        : SerializableReturnType<ReturnType<T & Function>>;
}

export default function generateFunction<F>(
    fn: F & SupplierFunction<F, ArgumentTypes<F & Function>[0]>
) {
    return async (payload: ArgumentTypes<F & Function>[0]) => {
        const result: SerializableReturnType<ReturnType<F & Function>> =
            await new Promise((resolve) => {
                resolve(fn(payload));
            });
        return await result;
    };
}

它像charm一样动态工作,还支持操作重载函数,因此可以对其进行类型化。如果您不希望文档对象模型值作为参数传递并从提供的函数返回类型到生成器,则可以将其添加到Serializables类型以限制类型。
Check this out in action

相关问题