如何缩小常量的类型



在下面的示例中,我希望强制所有函数都应以特定的格式[string, number]返回,但这些函数的输入参数可能会有所不同。

游乐场链接

type ReturnFormat = [string, number]
type Fn = (...args: any[]) => ReturnFormat
const A: Fn = () => ['one', 1]
const B: Fn = (input: number) => ['two', input]
type C = Parameters<typeof A>
type D = Parameters<typeof B>

然而,当我试图读回函数的参数时,CD都是any[],而不是nullinput: number。我该怎么做才能做到这一点?

这里的问题是您使用类型Fn声明变量AB。类型Fn只知道参数的类型应该是...any[]。因此,当您使用此类型声明变量时,有关用于赋值的实际函数的任何特定信息都将丢失。

您应该使用一个通用函数来初始化这些函数。

function createFunction<T extends Fn>(fn: T) { return fn }

我们可以将传递的函数T约束为Fn类型,但我们仍然返回原始类型T的函数。

当我们使用这个函数来创建这两个变量时,您会看到类型信息被保留了下来。

const a = createFunction(() => ['one', 1])
// const a: () => [string, number]
const b = createFunction((input: number) => ['two', input])
// const b: (input: number) => [string, number]
const c = createFunction((input: number) => ['two']) // Error: We broke the constaint!

游乐场


第二种选择是使Fn通用。但是,每次使用Fn来声明函数时,我们都必须明确地将参数类型赋予它。

type Fn<T extends any[] = void[]> = (...args: T) => ReturnFormat
const a: Fn = () => ['one', 1]
const b: Fn<[number]> = (input: number) => ['two', input]