Целочисленное именование параметров перегрузки, когда аргументы являются условным типом кортежа - PullRequest
0 голосов
/ 21 февраля 2019

В TypeScript 3.1 у меня есть универсальная функция, аргументы которой (TInput, string) или (string), в зависимости от того, является ли параметр типа универсального TInput extends undefined.В настоящее время я использую новую универсальную функцию остальных параметров для ввода аргументов функции в качестве условного типа кортежей:

function test (
    ...args: TInput extends undefined ? [string] : [TInput, string]): void
)

Это почти идеально работает.Когда я создаю экземпляр универсальной функции с конкретным типом, VSCode показывает только перегрузку, которая применяется к этому универсальному типу.Yay!

Но есть одна проблема: Intellisense в VSCode сообщает имена параметров как args_0 и args_1 вместо более понятных для человека имен, таких как input для универсального параметра (если он есть) и name для строкового параметра.

Есть ли способ присоединить более дружественные имена к этим параметрам, не теряя (правильный) Intellisense для количества параметров и типа (ов)?

КстатиХорошо с решением, которое не использует кортежи, пока основные требования работают хорошо, а именно: когда генерируется универсальная функция с реальным типом, и я наводю указатель мыши на функцию в VSCode, я вижу правильный счетчик параметров, имя(s) и тип (ы), которые действительны для этого конкретного типа.

Я попытался добавить перегрузки (см. Прокомментированный код ниже), но не мог понять, как заставить перегрузки компилироваться.Я получил: Сигнатура перегрузки не совместима с реализацией функции.ts (2394)

В более ранней итерации этого примера я мог использовать приведение типов для получения перегрузок при компиляции, но это в свою очередь нарушало Intellisense для числа параметров и типов, где "сломался""означает, что (в отличие от приведенного ниже кода) в Intellisense всегда отображались две перегрузки, даже когда параметр универсального типа должен был сузить список до одной допустимой перегрузки.

const makeTest = <TInput>() => {
//  Adding the overloads below doesn't work as expected. There are two problems: 
//    1. compiler error: "Overload signature is not compatible with function implementation. ts(2394)"
//    2. if I use a cast to get around the compile error, both overloads show in Intellisense regardless of TInput
//  function test (name: string): void; 
//  function test (input: TInput, name: string): void;
    function test (...args: TInput extends undefined ? [string] : [TInput, string]): void {
        // do stuff
    }
    return test;
}

// type inferred as: const f1: (args_0: string) => void
const f1 = makeTest<undefined>(); 

// type inferred as: const f2: (args_0: number, args_1: string) => void
const f2 = makeTest<number>();

Вот ссылка детская площадка для этого кода, чтобы вы могли увидеть проблему вживую.

Кстати, я знаю, что мог бы упростить это, изменив порядок параметров, но изменить его сигнатуру на JS непрактично.Я только могу изменить типизацию TS в этой точке.Кроме того, даже если параметры были изменены на противоположные, мне действительно нравится, как создание экземпляра универсального с определенным типом удалит недопустимую перегрузку, и я не знаю, будет ли это работать с традиционными необязательными параметрами.

1 Ответ

0 голосов
/ 21 февраля 2019

Я бы просто набрал assert для функции условного типа, зависящего от TInput, что даст вам лучший уровень интеллекта, который вы хотите.Вы не можете легко указать имена аргументов для кортежей в параметрах отдыха:

const makeTest = <TInput>() => {

    function test (...args: [string] | [TInput, string]): void {
        // do stuff
    }
    return test as (TInput extends undefined ? ((name:string) => void) : ((input: TInput, name: string) => void);
}

Или версия с реализацией и публичной подписью для makeTest:

function makeTest<TInput>(): (TInput extends undefined ? ((name: string) => void) : ((input: TInput, name: string) => void))
function makeTest<TInput>(): ((name: string) => void) | ((input: TInput, name: string) => void) {

    function test(...args: [string] | [TInput, string]): void {
        // do stuff
    }
    return test;
}
...