有没有更简单的方法来编写多个条件函数签名?

Is there an easier way of writing multiple condition function signatures?

我有第一个参数决定第二个参数的函数。 它的行为类似于 Foo

type stringF = (type: 'str', value: string) => void
type numberF = (type: 'num', value: number) => void
type booleanF = (type: 'bool', value: boolean) => void
...
... 

declare const Foo: stringF & numberF & booleanF //& etc..

一共有6种函数类型。这是一种痛苦,但可以控制。但是现在有一个额外的参数作为第一个参数,指定它是否应该是一个数组..

所以变成了:

type stringF = (arr: false, type: 'str', value: string) => void
type numberF = (arr, false, type: 'num', value: number) => void
type booleanF = (arr, false, type: 'bool', value: boolean) => void
...

type stringF = (arr: true, type: 'str', value: string[]) => void
type numberF = (arr, true, type: 'num', value: number[]) => void
type booleanF = (arr, true, type: 'bool', value: boolean[]) => void
...

现在有12种函数类型。正确输入函数似乎不值得麻烦

有没有更简单的方法来制作条件函数签名?

您可以使用条件类型为所有可能性创建单个签名:

type StringToType = { 
  str: string,
  num: number,
  bool: boolean
}
type MakeArrayIfTrue<TCondition, T> = TCondition extends true ? T[] :T;

type fn =  <MakeArray extends boolean, TypeKey extends keyof StringToType>(arr:  MakeArray, type: TypeKey, value: MakeArrayIfTrue<MakeArray, StringToType[TypeKey]>) => void

declare let fn : fn;
fn(true, "str", [""]);
fn(true, "bool", [""]); // error
fn(false, "str", [""]); // error

如果参数是联合,这与多重重载的行为有点不同。例如,这是有效的:

declare let b: boolean;
declare let strOrBool: "str" | "bool";
// Last parameter ca be boolean | string | boolean[] | string[]
fn(b, strOrBool, "") //ok
fn(b, strOrBool, [""]) //ok
fn(b, strOrBool, true) //ok
fn(b, strOrBool, 1) //this is still an error 

如果你想限制这种行为,我们可以更有创意,首先创建一个所有可能签名的联合,然后使用 返回一个行为类似于具有重载的函数的类型:

type StringToType = { 
  str: string,
  num: number,
  bool: boolean
}
type MakeArrayIfTrue<TCondition, T> = TCondition extends true ? T[] :T;

type UnionToIntersection<U> =  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type FnHelper<MakeArray extends boolean = boolean, TypeKey extends keyof StringToType = keyof StringToType> = 
    MakeArray extends any ? TypeKey extends any ? (arr:  MakeArray, type: TypeKey, value: MakeArrayIfTrue<MakeArray, StringToType[TypeKey]>) => void: never: never;
type fn = UnionToIntersection<FnHelper>;

declare let fn : fn;
fn(true, "str", [""]);
fn(true, "bool", [""]); // error
fn(false, "str", [""]); // error

declare let b: boolean;
declare let strOrBool: "str" | "bool";
fn(b, strOrBool, "") //error
fn(b, strOrBool, [""]) //error
fn(b, strOrBool, true) //error

在这种情况下,您应该使用 Generic。所以你的函数签名可能是这样的:

function myFunc<T>(value: T|T[]): void

它可以是数组也可以不是数组,你只需要在你的函数中检查它。而类型 T 代表所有不同的值类型。