具有keyof的Typescript函数不接受对象键值作为有效的keyof

时间:2019-02-27 14:31:09

标签: typescript

我有一个使用keyof功能的简单函数:

interface B {
  name: string;
  age: number;
}

function test(key: keyof B) {}

const c = {
  age: 'age'
}

test(c.age);

上述代码的问题是打字稿引发了type string is not assignable to keyof B错误。

如果keyof功能不能与对象键值一起使用,那又有什么意义呢?我不想添加as keyof B

3 个答案:

答案 0 :(得分:2)

由于隐式键入,

date将是一个字符串(c.age的类型为c)。您可以将c.age的类型定义为{age:string}。这也将限制您将其他值分配给keyof B属性并意外使用它们。

age

答案 1 :(得分:2)

问题在于,打字稿默认不会推断对象属性的文字类型(即使它们是const)。

您可以通过对字符串文字类型使用类型断言来解决此问题:

const c = {
  age: 'age' as 'age'
}

test(c.age);

或者您想为对象的所有属性推断字符串文字类型,您可以使用函数(我在这里使用iffe,但它可以是单独的函数)

const c = (<V extends string,  T extends Record<string, V>>(o: T) => o)({
  age: 'age'
});

test(c.age);

或者在3.4(尚未发布)中,您可以在对象上使用as const断言:

const c = {
  age: 'age'
} as const

test(c.age);

答案 2 :(得分:2)

原因是TypeScript推断c的类型为{age: string;},而不是{age: 'age';}

如果可以推断出后者,而不是前者,那么您将无法像这样更改c.age

const c = { age: 'age' }
c.age = 'somethingElse';

如果您直接使用文字'age'来调用它,它将按照广告中的说明工作。

您可以使用适当的类型覆盖TypeScript推断,如下所示:

const c: {age: 'age'} = {
  age: 'age',
};

这将使类型错误消失,并强制您不向文字文本字符串c.age分配任何内容给'age'