将枚举值映射到类型

编程入门 行业动态 更新时间:2024-10-28 07:26:39
本文介绍了将枚举值映射到类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

假设我有这样的代码:

// Events we might receive: enum EventType { PlaySong, SeekTo, StopSong }; // Callbacks we would handle them with: type PlaySongCallback = (name: string) => void; type SeekToCallback = (seconds: number) => void; type StopSongCallback = () => void;

在给出的API中,我可以使用$ $ b注册这样的回调 $ b

In the API I'm given, I can register such a callback with

declare function registerCallback(t: EventType, f: (...args: any[]) => void);

但是我想摆脱任何 any [] ,并确保我无法注册错误类型的回调函数。

But I want to get rid of that any[] and make sure I can't register an ill-typed callback function.

我意识到我可以做到:

type CallbackFor<T extends EventType> = T extends EventType.PlaySong ? PlaySongCallback : T extends EventType.SeekTo ? SeekToCallback : T extends EventType.StopSong ? StopSongCallback : never; declare function registerCallback<T extends EventType>(t: T, f: CallbackFor<T>); // Rendering this valid: registerCallback(EventType.PlaySong, (name: string) => { /* ... */ }) // But these invalid: // registerCallback(EventType.PlaySong, (x: boolean) => { /* ... */ }) // registerCallback(EventType.SeekTo, (name: string) => { /* ... */ })

这真的很漂亮,强大!感觉就像我在使用依赖类型:我基本上是在这里写了一个将值映射到类型的函数。

This is really nifty and powerful! It feels like I'm using dependent types: I basically wrote myself a function mapping values to types, here.

但是,我不知道TypeScript的全部功能类型系统,也许还有更好的方法将枚举值映射到这样的类型。

However, I don't know the full strength of TypeScript's type system and maybe there is an even better way to map enum values to types like this.

是否有更好的方法将枚举值映射到这样的类型?是否可以避免上述很大的条件类型? (实际上,我发生了很多事件,这简直是一团糟:当我将鼠标悬停在 CallbackFor 上时,VS Code表现出了巨大的表情,而我的棉绒呢真的想在每次:。)

Is there a better way to map enum values to types like this? Can I avoid a really big conditional type as above? (In reality I have many events, and it's kind of a mess: VS Code shows a huge expression when I hover over CallbackFor, and my linter really wants to indent after every :.)

我很想编写一个将枚举值映射为类型的对象,因此可以声明 registerCallback 使用 T 和 CallbackFor [T] ,但这不是似乎是一回事。

I'd love to write an object mapping enum values to types, so I can declare registerCallback using T and CallbackFor[T], but that doesn't seem to be a thing. Any insights are appreciated!

推荐答案

我们可以创建一个在枚举成员和回调类型之间映射的类型,但是如果直接在 registerCallback 中使用它,我们将无法正确推断出回调参数类型:

We can create a type that maps between the enum members and the callback types, but the if we use it directly in registerCallback we will not get correct inference for callback argument types:

type EventTypeCallbackMap = { [EventType.PlaySong] : PlaySongCallback, [EventType.SeekTo] : SeekToCallback, [EventType.StopSong] : StopSongCallback, } declare function registerCallback <T extends EventType>(t: T, f: EventTypeCallbackMap[T]): void; registerCallback(EventType.PlaySong, n => { }) // n is any

如果只有3个事件类型,则多个重载实际上是一个很好的解决方案:

If you have just 3 event types, multiple overloads are actually a pretty good solution:

declare function registerCallback(t: EventType.PlaySong, f: PlaySongCallback): void; declare function registerCallback(t: EventType.SeekTo, f: SeekToCallback): void; declare function registerCallback(t: EventType.StopSong, f: StopSongCallback): void; registerCallback(EventType.PlaySong, n => { }) // n is string

如果您有很多枚举成员,您还可以自动生成重载签名:

If you have a lot of enum member you could also generate the overload signature automatically:

type EventTypeCallbackMap = { [EventType.PlaySong]: PlaySongCallback, [EventType.SeekTo]: SeekToCallback, [EventType.StopSong]: StopSongCallback, } type UnionToIntersection<U> = (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never declare let registerCallback: UnionToIntersection< EventType extends infer T ? T extends T ? (t: T, f: EventTypeCallbackMap[T]) => void : never: never > registerCallback(EventType.PlaySong, n => { }) // n is string

请参见此处(并进行投票)答案)以解释 UnionToIntersection

See here (and up-vote the answer) for an explanation of UnionToIntersection

更多推荐

将枚举值映射到类型

本文发布于:2023-10-28 02:00:05,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1535168.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:类型

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!