打字稿类型字符串不能分配给keyof类型

时间:2019-01-23 09:48:25

标签: typescript

我有以下代码:

const KeyboardEventKeys = {
  Escape: 'Escape',
  Enter: 'Enter',
  Tab: 'Tab'
};

type KeyboardEventKeys = keyof (typeof KeyboardEventKeys);

function doSomething(key: KeyboardEventKeys) {}

当我将一个对象属性的值传递给函数时,它会对我大吼:

doSomething(KeyboardEventKeys.Enter);

一种解决方案是强制转换as KeyboardEventKeys,但这是多余的解决方案。没有它我该怎么办?

我也不想添加doSomething(key: KeyboardEventKeys | string),因为我将失去类型保护。

4 个答案:

答案 0 :(得分:1)

解决方案是使用枚举代替对象。

enum KeyboardEventKeys {
  Escape ='Escape',
  Enter = 'Enter',
  Tab = 'Tab'
};


function doSomething(key: KeyboardEventKeys) {}

您现在可以像这样传递变量

doSomething(KeyboardEventKeys.Enter);

答案 1 :(得分:1)

使用枚举的解决方案是一个很好的解决方案,我建议您使用它。

出现错误的原因是,打字稿不会推断const成员的字符串文字类型。创建const时,可以通过使用额外的函数来强制编译器推断字符串文字类型:

function createEnum<T extends { [P in keyof T]: P }>(o: T) {
    return o
}
const KeyboardEventKeys = createEnum({ // typed as { Escape: "Escape"; Enter: "Enter"; Tab: "Tab"; }

    Escape: 'Escape',
    Enter: 'Enter',
    Tab: 'Tab'
});

type KeyboardEventKeys = keyof (typeof KeyboardEventKeys);

function doSomething(key: KeyboardEventKeys) { }
doSomething("Enter")
doSomething("") //err

答案 2 :(得分:0)

您尝试过吗:

keyof { [key: string]: KeyboarEventKeys }

答案 3 :(得分:0)

TypeScript 3.4起,您可以通过使用特殊的as const强制转换构造来强制编译器保留文字类型。 所以在这里你可以写

const KeyboardEventKeys = {
  Escape: 'Escape',
  Enter: 'Enter',
  Tab: 'Tab'
} as const;

type KeyboardEventKeys = keyof typeof KeyboardEventKeys;

function doSomething(key: KeyboardEventKeys) {}

但是,最终我建议改用[const] enum KeyboardEventKeys { ... }