打字稿中的字符串键索引器具有更好的类型安全性

时间:2019-08-04 08:30:59

标签: typescript

我已经创建了this playground,下面是代码:

export enum KeyCode {
  Alt = 'meta',
  Command = 'command',
  // etc.
}

export type KeyStroke = KeyCode | string;

export interface Combination {
  combination: KeyStroke[];
}

export interface Sequence {
  sequence: KeyStroke[];
}

export type ShortcutItem = KeyStroke | KeyStroke[] | Combination | Sequence;

export interface Shortcut {
  [key: string]: ShortcutItem;
}

export type ShortcutMap =
  | {
      [key: string]: Shortcut;
    }
  | Shortcut;

export const buildShortcuts = (map: Shortcut) => {
  return []
}

function getShortcuts(shortcutMap: ShortcutMap, mapKey?: keyof typeof shortcutMap){
  const map = mapKey ? shortcutMap[mapKey] : shortcutMap;
  return buildShortcuts(map);
}

export const shortcutMapWithoutKey: ShortcutMap = {
  MOVE_LEFT: [KeyCode.Alt, 'a'],
  MOVE_RIGHT: [KeyCode.Command, 'd'],
};

export const shortcutMapWithKey: ShortcutMap = {
  one: {
    MOVE_UP: [KeyCode.Alt, 'b'],
    MOVE_DOWN: [KeyCode.Command, 'e'],
  },
  two: {
    MOVE_HERE: [KeyCode.Alt, 'c'],
    MOVE_THERE: [KeyCode.Command, 'f'],
  }
};

const a = getShortcuts(shortcutMapWithoutKey);
const b = getShortcuts(shortcutMapWithKey, "one");

ShortcutMap类型不能充分缩小联合类型。

是否可以通过某种程度地缩小联合来获得更好的类型安全性。

我在此行出现错误:

  return buildShortcuts(map);
  

'string |类型的参数组合|字符串[] |顺序|快捷方式{[key:string]:快捷方式; }”不能分配给“快捷方式”类型的参数。     不能将“字符串”类型分配给“快捷方式”类型。

1 个答案:

答案 0 :(得分:1)

我认为您造成类型混淆的部分原因是您将ShortcutMap定义为

export type ShortcutMap =
  | {
      [key: string]: Shortcut;
    }
  | Shortcut;

我希望在这里,地图只是

  {
      [key: string]: Shortcut;
  }

您可以采用的一种解决方案是避免合并类型,从而使类型更加明确/狭窄。

看看这个TypeScript playground

希望,会有所帮助。