首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Typescript:如何根据对象键/值类型在ES6映射中创建条目

Typescript:如何根据对象键/值类型在ES6映射中创建条目
EN

Stack Overflow用户
提问于 2019-02-27 21:51:44
回答 1查看 2.3K关注 0票数 4

我想使用Map而不是object map来声明一些键和值。但是Typescript似乎不支持ES6地图的索引类型,这是正确的吗?有什么解决方法吗?

此外,我还希望使值是类型安全的,以便映射中的每个条目都具有与键对应的值的正确类型。

下面是一些伪代码,它描述了我试图实现的目标:

代码语言:javascript
复制
type Keys = 'key1' | 'key2';

type  Values = {
  'key1': string;
  'key2': number;
}

/** Should display missing entry error */
const myMap = new Map([
  ['key1', 'error missing key'],
]);

/** Should display wrong value type error for 'key2' */
const myMap = new Map([
  ['key1', 'okay'],
  ['key2', 'error: this value should be number'],
]);

/** Should pass */
const myMap = new Map([
  ['key1', 'all good'],
  ['key2', 42],
]);

编辑:部分描述我的用例的更多代码

代码语言:javascript
复制
enum Types = {
  ADD = 'ADD',
  REMOVE = 'REMOVE',
};

/** I would like type-safety and autocompletion for the payload parameter */
const handleAdd = (state, payload) => ({...state, payload});

/** I would like to ensure that all types declared in Types are implemented */
export const reducers = new Map([
  [Types.ADD, handleAdd],
  [Types.REMOVE, handleRemove]
]);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-27 22:44:19

这是我所能想象到的最接近的结果,尽管我仍然不明白为什么我们不从一开始就使用普通的对象:

代码语言:javascript
复制
type ObjectToEntries = { [K in keyof O]: [K, O[K]] }[keyof O]

interface ObjectMap {
  forEach(callbackfn: (
    value: O[K], key: K, map: ObjectMap
  ) => void, thisArg?: any): void;
  get(key: K): O[K];
  set(key: K, value: O[K]): this;
  readonly size: number;
  [Symbol.iterator](): IterableIterator>;
  entries(): IterableIterator>;
  keys(): IterableIterator;
  values(): IterableIterator;
  readonly [Symbol.toStringTag]: string;
}

interface ObjectMapConstructor {
  new , K extends keyof any>(
    entries: E
  ): ObjectMap<{ [P in E[0][0]]: Extract[1] }>;
  new (): ObjectMap>;
  readonly prototype: ObjectMap;
}

const ObjectMap = Map as ObjectMapConstructor;

这个想法是为了制作一个新的界面,ObjectMap,它具体依赖于对象类型。O来确定它的键/值关系。然后你可以说Map构造函数可以充当ObjectMap构造函数。我还删除了可以更改实际存在的键的所有方法(以及has()方法是冗余的。true另外)。

我可以不厌其烦地解释每个方法和属性定义,但这需要大量的类型调整。简而言之,您想要使用K extends keyof OO[K]来表示通常由KVMap

构造函数更让人讨厌,因为类型推断不会以你想要的方式工作,所以保证类型安全需要两个步骤:

代码语言:javascript
复制
// let the compiler infer the type returned by the constructor
const myMapInferredType = new ObjectMap([
  ['key1', 'v'], 
  ['key2', 1],  
]);

// make sure it's assignable to `ObjectMap`: 
const myMap: ObjectMap = myMapInferredType;

如果你的myMapInferredType不匹配ObjectMap(例如,您缺少键或具有错误的值类型),然后myMap会给你带来错误。

现在您可以使用myMap作为一个ObjectMap,类似于使用Map实例,带有get()set(),并且它应该是类型安全的。

请再次注意..。对于一个更复杂、类型更复杂、功能不比普通对象多的对象来说,这似乎是一项很大的工作。我会严肃地警告任何使用Map,它的键keyof any(即,string | number | symbol)到强consider using a plain object相反,请确保您的用例确实需要Map

Playground link to code

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54907009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档