typescript 基于关闭第一个参数的函数参数动态类型

unguejic  于 2023-01-31  发布在  TypeScript
关注(0)|答案(3)|浏览(170)

现在我有一个非常通用的函数,当我的客户端与服务器对话时,它会被点击。所以为了保持它的灵活性,我这样做:

public call(method: string, ...parameters: any[]) {}

但是在我的服务器上,我将所有方法放在一起,如下所示:

MethodManager.methods({
    findOne: {
        function: function(collection: string, query: Object) {
            return model(collection).findOne(query).exec();
        }
    },
    find: {
        function: function(collection: string, query: Object, sortQuery: Object = {}) {
            return model(collection).find(query).sort(sortQuery).exec();
        }
    }
}

正如你所看到的,每个方法可能有不同的参数。当我在客户端写代码时,我不能使用Typescript的全部潜力,因为它是"any"类型转换的。
我怎样做才能让visual studio代码在我写这行代码时识别出:

this.socketManager.call('findOne',

它会弹出一个助手列表,如下所示:

(method: 'findOne', collection: string, query: Object)

但当我输入:

this.socketManager.call('find',

它给我:

(method: 'find', collection: string, query: Object, sortQuery: Object = {})

而不是毫无帮助的:

(method: string, ...parameters: any[])

这可能吗?这将对发展有极大的帮助。

dauxcl2d

dauxcl2d1#

我有一个类似的情况。当用户登录和注销时,我必须发送一个事件。我想创建一个sendEvent函数,这样如果我们传递第一个参数login type = 'LOG_IN',则第二个参数,即带有userId的payload对象是强制的,然而,如果事件类型=“LOG_OUT”,则第二个参数可以是可选的。这就是我如何处理的,您可以做类似的事情:

export type Event = { type: 'LOG_IN'; payload: { userId: string } } | { type: 'LOG_OUT' };

const sendEvent = <Type extends Event['type']>(
  ...args: Extract<Event, { type: Type }> extends { payload: infer TPayload } ? [type: Type,payload: TPayload] : [Type]
) => {
  // Send event stuff

};

sendEvent('LOG_IN', {userId: 'id1'})
sendEvent('LOG_OUT');
mrzz3bfm

mrzz3bfm2#

您可以在Typescript中对函数重载执行以下操作:https://www.typescriptlang.org/docs/handbook/functions.html
下面是一个例子:

function call(method: "find", collection: string, query: object): object;
function call(method: "findOne", collection: string, query: object, sortQuery: object): object[];
function call(method: "find" | "findOne", ...parameters: any[]): any {
    switch (method) {
        case "find": {
            const [collection, query] = parameters
            return {}
        }
        case "findOne": {
            const [collection, query, sortQuery] = parameters
            return [{}]
        }

    }
}

call("find", "collection", {})
call("findOne", "collection", {}, {})

call("find", "collection", {}, {}) // Error
call("findOne", "collection", {}) // Error
vyswwuz2

vyswwuz23#

我写了一个脚本来遍历所有的方法文件,解析它们并获取函数和参数。这个脚本在编译服务器代码时运行(获取更改),然后在客户端重新创建一个生成的methods.ts文件,我在启动时加载这个文件。

export function SERVER_METHODS(socketManager) {
    return {
        findOne: (collection: string, query: Object, cb?: Function)  => {
            socketManager.call('findOne', collection, query, cb);
        },
        find: (collection: string, query: Object, sortQuery: Object = {}, cb?: Function)  => {
            socketManager.call('find', collection, query, sortQuery, cb);
        },
        ...
    };
}

那么我是这样使用的:

public methods = SERVER_METHODS(this);

现在我们不这么做了

this.socketManager.call('findOne', ...)

我是这么做的:

this.socketManager.methods.findOne(

这就给了我那个函数的参数。相当手动的解决方案,但它工作正常,现在是自动化的。

相关问题