Применить ReturnType к типу объединения

TypeScript не может использовать ReturnType для типов объединения?

type NumberParser = (input: string) => number | DiplomacyError;
type StringParser = (input: string) => string | DiplomacyError;
type Parser = NumberParser | StringParser;

export interface Schema {
  [key: string]: Parser | Schema;
}

export type RawType<T extends Schema> = {
  [Property in keyof T]: T[Property] extends Schema
    ? RawType<T[Property]>
    : ReturnType<T[Property]>; // T[Property] marked as error
};

<T[Property]> выдает следующую ошибку:

Type 'T[Property]' does not satisfy the constraint '(...args: any) => any'.
  Type 'T[keyof T]' is not assignable to type '(...args: any) => any'.
    Type 'T[string] | T[number] | T[symbol]' is not assignable to type '(...args: any) => any'.
      Type 'T[string]' is not assignable to type '(...args: any) => any'.
        Type 'Parser | Schema' is not assignable to type '(...args: any) => any'.
          Type 'Schema' is not assignable to type '(...args: any) => any'.
            Type 'Schema' provides no match for the signature '(...args: any): any'.ts(2344)

person Davide Valdo    schedule 10.04.2021    source источник


Ответы (1)


Известная проблема TypeScript состоит в том, что ложная ветвь условного типа не сужает свои типы. Так что в T extends U ? F<T> : G<T> не берём G<T> и заменяем его чем-то вроде G<Exclude<T, U>>. Что касается компилятора, T в G<T> все еще может быть присвоено U, хотя для нас очевидно, что это не так. См. microsoft / TypeScript # 29188. Похоже, что для решения этой проблемы была проделана определенная работа по адресу microsoft / TypeScript # 24821, но не было слито. Мне не ясно, будет ли решена эта проблема и когда это произойдет.

А пока достаточно легко (если это раздражает) сделать такое сужение самостоятельно, когда это необходимо:

export type RawType<T extends Schema> = {
    [K in keyof T]: T[K] extends Schema
    ? RawType<T[K]>
    : ReturnType<Exclude<T[K], Schema>>;
};

Или возможно

export type RawType<T extends Schema> = {
    [K in keyof T]: T[K] extends Schema
    ? RawType<T[K]>
    : ReturnType<Extract<T[K], Parser>>;
};

площадка ссылка на код

person jcalz    schedule 10.04.2021
comment
Спасибо, пожалуйста, посмотрите отредактированный вопрос, если сможете. - person Davide Valdo; 10.04.2021
comment
Похоже, что исходный вопрос был решен, и если у вас есть дополнительные вопросы (а не что-то сломанное в исходном ответе), вам, вероятно, следует опубликовать новый вопрос по этому поводу вместо того, чтобы расширять объем уже отвеченного вопроса. Это также поможет вам по-новому взглянуть на него (тем более, что мой скоро закроется на ночь, так как в моем часовом поясе уже поздно). Удачи! - person jcalz; 10.04.2021
comment
stackoverflow.com/questions/67030605 / но действительно ли это дополнительный вопрос? Я тоже закрывал глаза, не мог уснуть из-за этого - person Davide Valdo; 10.04.2021