Обрезать / сопоставить объединение определенной функции и типа T, а также отдельного T с функцией - PullRequest
0 голосов
/ 09 октября 2018

Извините за сложное название, я не мог придумать лучшего.

Дополнительный контекст: Это должно работать на TS 2.8.4

Мне нужна небольшая помощь стип отображения

// Input types:
type FunctionOrObject<Arg, Result> =
| ((arg: Arg) => Partial<Result>)
| Partial<Result>;

interface ExampleArg {
  disabled: boolean;
}
interface ExampleResult {
  root: string;
  sub: string;
}

type FuncOrObj = FunctionOrObject<ExampleArg, ExampleResult>;
type Standalone = ExampleResult;

// Expected should have the type (arg: Arg) => Partial<Result>
type Expected = MagicMappingType<FuncOrObj >;

//  Expected2 should have the type (...args: any[]) => Partial<Result>
type Expected2 = MagicMappingType<Standalone>;

Сейчас я пришел с этим, но он не работает идеально

type _TrimToFunction<T> = T extends (...args: any[]) => any ? T : never;

// Expected has type (arg: ExampleArg) => Partial<ExampleResult> - Correct!
type Expected = _TrimToFunction<FuncOrObj>;

// Expected2 is never - Wrong!
type Expected2 = _TrimToFunction<Standalone>;

Это, очевидно, происходит потому, что автономный интерфейс ExampleResult не проходитусловие _TrimToFunction и, таким образом, отображается на never.Но если я изменю _TrimToFunction на это:

type _TrimToFunction<T> = T extends (...args: any[]) => any ? T : (...args: any[]) => T;

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

type Expected =
  | ((arg: ExampleArg) => Partial<ExampleResult>)
  | ((...args: any[]) => Partial<Partial<ExampleArg>>)

type Expected2 = (...args: any[]) => Partial<ExampleResult>

Это вызвано тем, что вторая часть объединения FuncOrObj не прошла проверку состояния и не сопоставилась с типом "else".

Возможно ли достичь даже с помощью TS 2.8?

1 Ответ

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

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

Простое решение состоит в том, чтобы немного изменить условие.Мы можем использовать Extract.Если мы можем извлечь Function из T, мы возвращаем это, если мы не можем, мы возвращаем новую функцию, возвращающую Partial<T>

type _TrimToFunction<T> = Extract<T, Function> extends never ? (...args: any[]) => Partial<T>: Extract<T,Function>;

// Expected has type (arg: ExampleArg) => Partial<ExampleResult> - Correct!
type Expected3 = _TrimToFunction<FuncOrObj>;

// Expected2 is (...args: any[]) => Partial<ExampleResult>
type Expected4 = _TrimToFunction<Standalone>;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...