简体   繁体   English

如何使用隐式键将对象文字声明为记录

[英]How to declare object literal as Record with implicit keys

If a constant object literal is created without declaring a type, it will infer the keys from the value:如果在没有声明类型的情况下创建了一个常量对象文字,它将从值中推断出键:

const OBJ = {foo: 42, bar: 42}

This will become a Record<'foo' | 'bar', number>这将成为一个Record<'foo' | 'bar', number> Record<'foo' | 'bar', number> , which means IDEs will be helpful to offer auto-completion when typing OBJ.fo etc. Record<'foo' | 'bar', number> ,这意味着 IDE 将有助于在键入OBJ.fo等时提供自动完成OBJ.fo

If the same object is declared like this:如果同一个对象是这样声明的:

const OBJ: Record<string, number> = {foo: 42, bar: 42}

then IDEs will pretend not to know that OBJ has keys foo and bar , since OBJ is a record of any string key.那么 IDE 会假装不知道OBJ有键foobar ,因为OBJ任何字符串键的记录。 :( :(

Now, if the values are simple primitives, omitting the type and relying on implicit inferred types usually works fine, but if the record is more complex, such as a Record<string, MyEnum> or Record<string, (x: string, y: number) => number> etc, doing so will lose the type information of the values :现在,如果值是简单的原语,省略类型并依赖隐式推断类型通常可以正常工作,但如果记录更复杂,例如Record<string, MyEnum>Record<string, (x: string, y: number) => number>等,这样做会丢失的类型信息:

enum MyEnum {
  A = 42,
  B = 85
}

const OBJ = {foo: A, bar: B};

Now OBJ will be a Record<'foo' | 'bar', number>现在OBJ将是一个Record<'foo' | 'bar', number> Record<'foo' | 'bar', number> , not a Record<'foo' | 'bar', MyEnum> Record<'foo' | 'bar', number>不是Record<'foo' | 'bar', MyEnum> Record<'foo' | 'bar', MyEnum> . Record<'foo' | 'bar', MyEnum>

What I want is to declare a dictionary where the type of the values is given in the declaration, but keys are inferred.我想要的是声明一个字典,其中在声明中给出了值的类型,但推断出键。

The only ways I've found are:我发现的唯一方法是:

  1. Type each value键入每个
const OBJ = {foo: <MyEnum>A, bar: <MyEnum>B};
  1. Declare keys separately单独声明键
type Keys = 'foo' | 'bar';
const OBJ: Record<Keys, MyEnum> = {foo: A, bar: B};

Is there a better way, where the keys are inferred by the literal but the values are declared on the entire Record ?有没有更好的方法,键是由文字推断的,但值是在整个Record上声明的?

I am not sure which TypeScript version you are using.我不确定您使用的是哪个 TypeScript 版本。 Also, your example has an error, you need to use MyEnum.A instead of just A .此外,您的示例有一个错误,您需要使用MyEnum.A而不仅仅是A

Let's look at your example:让我们看看你的例子:

enum MyEnum {
  A = 42,
  B = 85
}

const OBJ = {foo: MyEnum.A, bar: MyEnum.B};

OBJ has the correct type: { foo: MyEnum; bar: MyEnum; } OBJ具有正确的类型: { foo: MyEnum; bar: MyEnum; } { foo: MyEnum; bar: MyEnum; } { foo: MyEnum; bar: MyEnum; } . { foo: MyEnum; bar: MyEnum; } . Tested in 3.9 > typescript.3.9 >打字稿中测试。

Try on TS Playground试玩TS Playground


Regarding your requirements:关于您的要求:

What I want is to declare a dictionary where the type of the values is given in the declaration, but keys are inferred.我想要的是声明一个字典,其中在声明中给出了值的类型,但推断出键。

You can use Generics function to infer type:您可以使用泛型函数来推断类型:

enum MyEnum {
  A = 42,
  B = 85
}

function fixType<T extends string>(value: Record<T, MyEnum>): Record<T, MyEnum> {
  return value
}

const OBJ = fixType({foo: MyEnum.A, bar: MyEnum.B})

And now OBJ has Record<"foo" | "bar", MyEnum>现在OBJRecord<"foo" | "bar", MyEnum> Record<"foo" | "bar", MyEnum> type. Record<"foo" | "bar", MyEnum>类型。

Try on TS Playground试玩TS Playground


If you are using Enum , you may be interested in this issue .如果您正在使用Enum ,您可能会对这个问题感兴趣。 To sum up, even if you specified which numbers your enum supports, TS still allows assigning any number...总而言之,即使您指定了您的枚举支持哪些数字,TS 仍然允许分配任何数字...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM