打字稿:从带有索引签名的对象中获取密钥

时间:2019-05-29 19:23:56

标签: typescript

我正在从TypeScript模块导入以下类型和函数:

type Attributes = {
  [key: string]: number;
};

function Fn<KeysOfAttributes extends string>(opts: { attributes: Attributes }): any {
  // ...
}

我无法修改上面的代码。

然后,将以下代码实现到自己的模块中:

// variant 1
const attributes = { // this object is hard coded (not dynamically generated)
  foo: 1,
  bar: 2,
  baz: 3
};

type Type = typeof attributes;
type Keys = keyof Type;

Fn<Keys>({
  attributes
});

一切正常。现在,我想将类型Attributes的类型分配给常量attribute,因为我想确保键是字符串,值是数字。所以我修改了我的代码:

// variant 2
const attributes: Attributes = {
  foo: 1,
  bar: 2,
  baz: 3
};

type Type = typeof attributes;// equals {[key: string]: number;}
type Keys = keyof Type;// equals string | number. Why ?

Fn<Keys>({// Here, I would like Keys to be "foo" | "bar" | "baz", instead I have string | number
  attributes
});

我在Fn<Keys>({行上收到以下错误:

Type 'string | number' does not satisfy the constraint 'string'.
Type 'number' is not assignable to type 'string'.ts(2344)

当索引签名专门指定键是字符串时,我不明白为什么类型Keys等于string | number

如何确保"foo" | "bar" | "baz"类型作为类型参数而不是string | number传递?

我可以忍受第一个变种,但是我不明白为什么第二个变种不起作用。 有想法吗?

非常感谢

1 个答案:

答案 0 :(得分:0)

  

如何确保“ foo” | “酒吧” | “ baz”类型作为类型参数而不是字符串|数字?

您可以通过为attributes引入通用类型参数来实现此目的:

type Attributes = {
  [key: string]: number;
};

function Fn<KeysOfAttributes extends keyof T, T extends Attributes>(opts: { attributes: T }): any {
  // ...
}

const attributes = {
  foo: 1,
  bar: 2,
  baz: 3,
};

Fn({
  attributes
});

Typescript能够自行推断类型,因此您甚至不需要TypeKeys

Playground