在 TypeScript 中使用通用类型(特定任务)

问题描述 投票:0回答:1

我正在尝试输入名为

route
的函数。我在我的 Express 项目中使用它

const morph = (params: Function[]) => (req: Request) => params.map(f => f(req))


const applyTransformers = (transformers: Function[]) => (response: any) => {
    for (const transformer in transformers) {
        response = transformer(response)
    }
    return response
}

export const route = <
  H extends (...args: any[]) => Promise<any>,
  T extends any[] = Parameters<H>,
  P extends Function[] = { [K in keyof T]: (req?: Request) => T[K] }
>(handler: H, params: P = [] as P, transformers: Function[] = []): RequestHandler | ErrorRequestHandler => (
    wrap(
      async (req: Request, res: Response) => {
        // eslint-disable-next-line no-debugger
        // debugger

        const result = await handler(
          ...morph(params)(req)
        )

        res.send(applyTransformers(transformers)(result))
      }
    )
  )

// Usage: 
// id = (req: Request): string => req.params.id
// customParam = (param: string) => (req: Request): string => req.params[param]
// ... 
// app.get('/example-route/:id/blah/:blah', route(handler, [id, customParam('blah')])
//                                        handler: (string, string) => Promise<any>

问题如下: 我不想在使用路由函数时为其提供泛型类型。我希望它理解

handler
params
的类型“匹配”,如果它们不“匹配”,我想得到一个 TypeError。但它并没有按预期工作。例如,如果
handler
的类型为
(string, number) => Promise<any>
并且
params
的类型为
[(Request) => number, (Request) => string]
TypeScript 不会给我错误。

typescript typing typescript-types
1个回答
0
投票

我对原始代码进行了一些重构,但这个具体示例的解决方案是使泛型类型 P 扩展它所分配的类型。那就是替换

P extends Function[] = { [K in keyof T]: (req?: Request) => T[K] }

P extends { [K in keyof T]: (req?: Request) => T[K] } = { [K in keyof T]: (req?: Request) => T[K] }

这样代码看起来像:

export const route = <
  H extends (...args: any[]) => Promise<any>,
  T extends any[] = Parameters<H>,
  P extends { [K in keyof T]: (req?: Request) => T[K] } = { [K in keyof T]: (req?: Request) => T[K] }
>(handler: H, params: P = [] as P, transformers: Function[] = []): RequestHandler | ErrorRequestHandler => (
    wrap(
      async (req: Request, res: Response) => {
        // eslint-disable-next-line no-debugger
        // debugger

        const result = await handler(
          ...morph(params)(req)
        )

        res.send(applyTransformers(transformers)(result))
      }
    )
  )
© www.soinside.com 2019 - 2024. All rights reserved.