Функциональный параметр Динамический тип, основанный на первом параметре - PullRequest
0 голосов
/ 24 ноября 2018

Прямо сейчас у меня есть очень общая функция, которая, когда мой клиент общается с моим сервером, срабатывает.Таким образом, чтобы сделать его очень гибким, я делаю это:

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, потому что он «любой» приведен.

Как я могу сделать это так, чтобы код 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[])

Возможно ли это?Это было бы решительной помощью для развития.

Ответы [ 2 ]

0 голосов
/ 24 ноября 2018

Мне удалось добиться этого, написав скрипт, который просматривает все файлы методов, анализирует их и извлекает функции и параметры.Этот скрипт запускается при компиляции кода сервера (собирает изменения), а затем заново создает сгенерированный файл method.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(

И это дает мне параметры для этой функции.Довольно ручное решение, но оно работает и теперь автоматизировано.

0 голосов
/ 24 ноября 2018

Вы можете сделать что-то подобное с перегрузками функций в 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...