【问题标题】:Typescript: Get key from object with indexed signature打字稿:从具有索引签名的对象中获取密钥
【发布时间】:2019-05-30 03:35:09
【问题描述】:

我正在从 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&lt;Keys&gt;({ 行收到以下错误:

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

我不明白为什么类型Keys等于string | number,当索引签名明确指定key是一个字符串?

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

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

非常感谢

【问题讨论】:

  • 您将类型扩展为字符串索引类型,编译器尽职尽责地期望它可以有任何键。也就是说,没有什么可以阻止程序中的某些代码执行attributes.potato = 123。所以keyof typeof attributesstring(好吧,| number 是为了方便)。如果您想要两全其美,请创建一个像 const asAttributes = &lt;A extends Attributes&gt;(a:A) =&gt; a 这样的辅助函数,然后将其称为 const attributes = asAttributes({foo: 1, bar: 2, baz:3});

标签: typescript


【解决方案1】:

我怎样才能确保"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

【讨论】:

    猜你喜欢
    • 2021-11-12
    • 1970-01-01
    • 2021-05-30
    • 2018-09-05
    • 1970-01-01
    • 2018-12-15
    • 2020-02-19
    • 1970-01-01
    • 2019-04-23
    相关资源
    最近更新 更多