如何将联合类型指定为对象键Typescript

福斯特

我需要一种键入对象的方法,其中键是特定类型的“事件”字段的值,而值是采用相同类型数据子类型的对象的回调数组

我尝试使用映射类型,但是我是TypeScript的初学者,对此确实很挣扎。

// I have this type structure, where the event is always a string, but the data can be anything (but is constrained by the event)

interface EventTemplate {
  event: string;
  data: any;
}

export interface CreateEvent extends EventTemplate {
  event: 'create_game';
  data: {
    websocketID: 'string';
  };
}

export interface JoinEvent extends EventTemplate {
  event: 'join_game';
  data: {
    gameID: 'string';
  };
}

export interface MessageEvent extends EventTemplate {
  event: 'message';
  data: string;
}

export type WSEvent = CreateEvent | JoinEvent | MessageEvent;

// I want an object like this

type callbacks = {
  [key in WSEvent['event']]: ((data: WSEvent['data']) => void)[];
};

// Except that it forces the data structure to match with the key used. IE using a specific WSEvent rather than a generic one

// Something along the lines of:

type callbacks = {
  [key in (T extends WSEvent)['event']]: ((data: T['data']) => void)[];
};
// ...only valid..

const callbacks: callbacks = {
  // So this should be valid:
  message: [(data: MessageEvent['data']): void => {}, (data: MessageEvent['data']): void => {}],

  // But this should not be valid, as CreateEvent doesn't have the event 'join_game'
  join_game: [(data: CreateEvent['data']): void => {}],
};

如果有帮助,我很高兴对以上任何内容进行重组。

Lukasgeiter

我们本质上需要的是一种通过提供事件名称来查找整个事件类型的方法。这可以使用条件帮助程序类型来完成

type EventByName<E extends WSEvent['event'], T = WSEvent> = T extends {event: E} ? T : never;

第一个通用参数E必须是事件名称之一。第二个是我们要缩小范围的联合类型。默认为,WSEvent因此无需指定。然后,条件表达式仅以并集类型返回扩展的那些事件{event: E}(其中E是事件名称)。

一旦有了helper类型,就可以很容易地为回调调整现有的映射类型:

type Callbacks = {
  [E in WSEvent['event']]: ((data: EventByName<E>['data']) => void)[];
};

操场


有关的名称的旁注callbacks建议对类型使用PascalCase。这样可以更轻松地与变量区分开。我已在示例中将其更改为Callbacks

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在Python 3.5中,如何将函数指定为类型提示?

如何在Typescript中将类定义指定为参数类型

TypeScript:返回类型具有指定为参数的所有键

在Typescript中,如何将通用容器类型的对象合并到对象类型的通用容器中?

通过类型键使对象成为联合类型

Typescript如何将接口的动态([键:类型]:类型)和静态类型混合使用

如何将渲染器指定为SVG?

Typescript如何将类型键映射到camelCase

如何将TypeScript对象类型转换为TypeScript中的联合类型,如Object.values()?

Clojure Spec:如何将元组指定为函数参数?

如何将元组的联合转换为对象类型

如何将null的等效项指定为struct类型的默认参数

如何将变量绑定为多种类型?LINQ

如何将断点条件指定为“小于”命中数?

如何将输入指定为日期时间?

从键的联合创建对象类型

如何将 PySpark 函数的返回类型指定为数据帧?

了解 R 如何将绘图指定为对象

如何将类型定义为像 [key: string] 键/值结构这样定义的对象键列表 - TypeScript

如何将特定的字符串值指定为 dart 中的类型

React - 如何将对象中的图标指定为值

如何使用对象接口的键路径数组的联合类型作为接口中这些键路径的联合类型?

在 TypeScript 中,如何将联合的每个值映射到单独的类型?

使用python创建类对象,如何将特定类型指定为条目?

如何将 2 个联合类型映射到 JavaScript Map 对象?

TypeScript - 如何要求一个键具有指定类型的对象?

如何将 List<MyCustomType> 指定为 UML 接口属性的“返回类型”

如何将 TypeScript 对象转换为带有键的对象的联合

如何从 TS 文字联合类型推断对象的键和值?