本人初学 ts,不是很清楚该怎么为这个问题归纳出一个标题,请见谅。
具体问题描述
我打算自己给 koa 写一个中间件 return
,具体是一个具有对象属性的函数,简要描述如下:
const RETURN_METHODS_CODES = { ok: 200, notFound: 404, /* ... */ }
const koaReturn = (statusCode: number) => (msg?: string, extras?: object) => {...}
for (const method in RETURN_METHODS_CODES) {
koaReturn[method] = koaReturn(RETURN_METHODS_CODES[method])
// => koaReturn.ok = koaReturn(200)
}
ctx.return = koaReturn
而在挂载到 koa 的全局 ctx
对象时需要为其指定一个类型。我想要 ts 能够自动在我扩展 RETURN_METHODS_CODES
对象时更新类型定义,因此在百度了一堆博客,翻了 handbook 里的各种定义后大杂烩出一个 ts 的定义如下:
const RETURN_METHODS_CODES = { ok: 200, notFound: 404, /* ... */ } as const
type ReturnMethods = keyof typeof RETURN_METHODS_CODES
// type ReturnMethods = "ok" | "notFound"
type ReturnSimplified = {
[K in ReturnMethods]: (msg?: string, extras?: object) => void
}
interface Return extends ReturnSimplified {
(code: number): (msg?: string, extras?: object) => void;
}
declare module 'koa' {
interface DefaultContext extends DefaultContextExtends {
return: Return
}
}
但是 ts 却在 for 循环内报错,报错信息:
koaReturn[method] = koaReturn(RETURN_METHODS_CODES[method])
// ^^^^^^
元素隐式具有 "any" 类型,因为类型为 "string" 的表达式不能用于索引类型 "(code: number) => (msg?: string | undefined, extras?: object | undefined) => void"。在类型 "(code: number) => (省略) => void" 上找不到具有类型为 "string" 的参数的索引签名。
去网上搜了一圈,找到了这个 stackoverflow 上的提问,尝试修改代码为:
let method: ReturnMethods
for (method in RETURN_METHODS_CODES) {
koaReturn[method] = koaReturn(RETURN_METHODS_CODES[method])
}
依然无效,报错位置不变,信息为:
元素隐式具有 "any" 类型,因为类型为 ""ok" | "notFound"" 的表达式不能用于索引类型 "(code: number) => (msg?: string | undefined, extras?: object | undefined) => void"。类型“(code: number) => (省略) => void”上不存在属性“ok”。
在此请问各位大佬,这个类型注解应该如何正确书写?还是我应该尝试换一种更方便于写注解的函数?已经摆烂到想写个 any 上去了
你修改后的写法是没有问题的,是否忘记指定
koaReturn
类型为Return
?另一种写法