【问题标题】:How to inherit narrowed type from function argument?如何从函数参数继承缩小类型?
【发布时间】:2021-09-20 11:50:45
【问题描述】:

我有一个函数接受另一个函数作为参数。参数是联合类型的函数,也可能有参数,也可能没有参数。

type innerFn = () => void | (arg: string) => void | (arg: number) => void | (arg: {}) => void

function mainFn (innerFn: InnerFnType) {
   function run(arg?: *any*) {
      innerFn()
   }
   return run
}

我想知道 run 参数是否可以根据传递给 mainFn 的函数来继承。

用例是:

const concreteInnerFn: InnerFnType = (arg: string) {
     do something
}

const run = mainFn(concreteInnerFn)

run("hello")  // OK
run(25) // ERROR
run({hello: true}) // ERROR

即如果我使用(arg: string) => void 作为innerFn,当我尝试使用run() 时,它应该要求输入字符串类型的参数。

希望它足够清楚

【问题讨论】:

    标签: typescript type-inference typescript-generics


    【解决方案1】:

    你可以做到的:

    type InnerFn =
      | (() => void)
      | ((arg: string) => void)
      | ((arg: number) => void)
      | ((arg: Record<string, unknown>) => void)
    
    const main = <
      Params extends Parameters<InnerFn>,
      >(fn: (...params: Params) => void) =>
      (...args: Params) => fn(...args)
    
    /**
     * Ok
     */
    const result0 = main(() => { }) // ok
    result0() // ok
    const result1 = main((a: string) => { })// ok
    result1('hello') // ok
    const result2 = main((a: number) => { }) // ok
    result2(42) // ok
    const result3 = main((a: { age: number }) => { }) // ok
    result3({ age: 42 })
    
    /**
     * Errors
     */
    const result4 = main((a: Promise<number>) => { }) // expected error
    const result5 = main((a: number[]) => { }) // expected error
    

    Playground

    说明

    请不要使用{} 作为类型,因为它是非常通用的类型。一切都是 javascript 和 typescript 中的对象。因此{} 不能用作约束。最好使用Record&lt;string, unknown&gt; 来实现此目的。

    Parameters - 返回传递函数的所有参数的元组。

    附:我希望你不介意我使用箭头函数而不是function。我不是说它更好,它只是一种风格的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      • 1970-01-01
      • 1970-01-01
      • 2022-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多