машинописные условные типы: вывод работает, но компилятор отклоняет реализацию - PullRequest
0 голосов
/ 30 октября 2018

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

Пример, это определение:

type ExportType<InputType extends string|undefined> =
    string extends InputType ? undefined : ()=>void;

function convert<InputType extends string|undefined>(input: InputType): ExportType<InputType>;

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

В сущности, подпись говорит "если параметр string, я верну ()=>void, если это undefined, я верну undefined.

И это прекрасно работает. Игра с convert("x") и convert(undefined) показывает, что машинопись соответствует этому определению.

Однако при попытке реализовать эту функцию:

type ExportType<InputType extends string|undefined> =
    string extends InputType ? undefined : ()=>void;

function convert<InputType extends string|undefined>(input: InputType): ExportType<InputType> {
    if (input) {
        return ()=>{console.log("OK");};
    } else {
        return undefined;
    }
}

Это не компилируется. Машинопись говорит:

error TS2322: Type '() => void' is not assignable to type 'ExportType<InputType>'.

         return ()=>{console.log("OK");};
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Но эта строка находится в if (input), поэтому в этот момент мы знаем, что ввод не undefined, поэтому он должен быть string, и поэтому мы должны вернуть () => void ... Но, похоже, компилятор просто недостаточно умен, чтобы это увидеть.

Изменение этой строки на:

    return <any>(()=>{console.log("OK");});

Заставляет это работать, но это разочаровывает ...

Так есть ли способ написать полностью безопасную и проверенную реализацию этой сигнатуры, которую машинопись позволяет нам выразить?

1 Ответ

0 голосов
/ 30 октября 2018

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

type ExportType<InputType extends string|undefined> =
    string extends InputType ? undefined : ()=>void;

function convert<InputType extends string|undefined>(input: InputType): ExportType<InputType> 
function convert(input: string|undefined): undefined | (()=>void) {
    if (input) {
        return ()=>{console.log("OK");};
    } else {
        return undefined;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...