Trim/Map 特定函数和类型 T 的联合,以及函数的独立 T

Trim/Map a union of a specific function and a type T, as well as a standalone T to a function

抱歉,标题太复杂了,我想不出更好的了。

其他上下文:这需要在 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 实现我想要实现的目标?

你在最后一个片段中得到一个意外类型的原因是如果类型参数是裸的,条件类型分布在联合上。阅读 docs 了解更多信息。

简单的解决办法是稍微改变一下条件。我们可以使用 Extract。如果我们可以从 T 中提取一个 Function,我们 return 如果我们不能,我们 return 一个新函数 returning 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>;