typescript - Typescript: typing many similar export values
问题描述
I have a module, that contains handlers for my API calls. It looks something like this:
// ./handlers.ts
export function handler1({ api }) { /* ... */ }
export function handler2({ api, config }) { /* ... */ }
export function handler3({ api }) { /* ... */ }
// ./index.ts
import * as handlers from './handlers'
app.post('/', (req, res, next) => {
const handler = determineHandlerName()
if(handler in handlers) {
handlers[handler](api)
}
})
Is there an elegant way to tell typescript the handlers
object looks like this?
interface Handlers {
[key: string]: (Api) => void
}
解决方案
从 TypeScript 3.6+ 开始,类型的handler[keyOfHandlers]
推断如下:
import * as handlers from './handlers'
declare const handlerName: keyof typeof handlers;
const handler = handlers[handlerName];
/*
handler: (({ api }: { api: any; }) => void)
| (({ api, config }: { api: any; config: any; }) => void)
| (({ api }: { api: any; }) => void)
*/
因此,推断的handlers
对象类型在技术上是正确的。
问题出在这个地方:
if (handler in handlers) {
// Here, `handler` still has type `string`,
// which is the opposite of what we want.
// We could do this, however:
const handlerName = handler as keyof typeof handlers;
handlers[handlerName]({ api });
}
正如我们所见,问题在于 TypeScript 不handler
保护if (handler in handlers)
.
另一个解决方案是创建一个自定义类型保护:
const isKeyOf = <T>(key: any, obj: T): key is keyof T => key in obj;
// then:
if (isKeyOf(handler, handlers)) {
handlers[handler](api); // works fine
}
推荐阅读
- c# - Xaml ListView 以编程方式 C# 导致奇怪的行为
- android - 更改上标文本的大小
- javascript - 有没有办法限制对 aws 服务的访问以仅在使用 javascript 的特定网站上获得访问权限?
- html - 如何添加嵌入视频的 OG 元标记?
- stata - 如何让Stata在每次循环迭代中等待用户输入?
- mysql - 联合视图丢失记录
- jquery - 滚动/页面加载时淡入元素
- string - 如果包含在输入中,如何摆脱 https
- python - ValueError:无法为具有形状“(?,30)”的张量“Placeholder_26:0”提供形状(261、25088)的值
- batch-file - 如何做可以通过bat文件检查进程的循环