英文:
How do I assert an ojbect to only have properties from a string union with TypeScript?
问题
Here's the translated code portion:
这是一个示例:
type supportedChains = 'eth_mainnet' | 'eth_testnet'
// 我想确保 fixtures 只有 eth_mainnet 和 eth_testnet 属性
const fixtures = {
eth_testnet: {
// ...
},
} as { [chain in supportedChains]: any }
If you need further assistance with this code or additional reading material, please let me know.
英文:
Here's an example:
type supportedChains = 'eth_mainnet' | 'eth_testnet'
// I want to make sure fixtures only have eth_mainnet and eth_testnet props
const fixtures = {
eth_testnet: {
// ...
},
} as ??
What I've tried for ??
:
- initially
{ [chain: supportedChain]: any }
– gettingAn index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.ts(1337)
- next,
{ [chain in supportedChain]: any }
– this doesn't give an error, but also doesn't guard against unwanted props
Not sure how to seach for this, please suggest how to implement this and ideally some further reading.
答案1
得分: 1
You should use satisfies operator for this and additionally adding const assertion would be great:
const fixtures = {
eth_mainnet: 'some value',
eth_testnet: 'some value 2',
} as const satisfies Record<supportedChains, string>
The benefit of this approach is that it prevents the compiler from widening the type of the fixtures
. With regular type definition, the type of fixtures
will be: Record<supportedChains, string>
, however, with the satisfies
and const assertion
, it will take the exact values from the object:
{
eth_mainnet: 'some value',
eth_testnet: 'some value 2',
}
英文:
You should use satisfies operator for this and additionally adding const assertion would be great:
const fixtures = {
eth_mainnet: 'some value',
eth_testnet: 'some value 2',
} as const satisfies Record<supportedChains, string>
The benefit of this approach is that it prevents the compiler from widening the type of the fixtures
. With regular type definition the type of fixtures
will be: Record<supportedChains, string
, however with the satisfies
and const assertion
it will take the exact values from the object:
{
eth_mainnet: 'some value',
eth_testnet: 'some value 2',
}
答案2
得分: 1
设置类型明确,您的对象将受到不希望的属性的保护。当使用 as
关键字时,您只是告诉编译器将对象视为与编译器推断的类型不同的东西。这被称为类型断言。
现在您想要使用的是映射类型。顾名思义,这会将您的联合值映射为对象属性键。此外,您可以添加一个 ?
使属性变成可选的。(=> 如果不是所有联合值都是属性,对象仍然有效)
type SupportedChains = "eth_mainnet" | "eth_testnet";
const fixtures: {[Chain in SupportedChains]?: any} = {
eth_testnet: {},
eth_mainnet: {},
extra_prop: {}
//~~~~~~~~~~ -> 类型 '{ eth_testnet: {}; eth_mainnet: {}; extra_prop: {}; }' 不能分配给...
};
英文:
Set the type explicitly and your object will be guarded against unwanted props. When using the as
keyword you only tell the compiler to treat the object as something different than the type the compiler infers the object to be. This is called Type Assertion.
Now what you want to use is a Mapped Type. As the name implies this maps your union values as object property keys. Additionally you could add a ?
to make the properties optional. (=> object is still valid if not all union values are there as properties)
type SupportedChains = "eth_mainnet" | "eth_testnet";
const fixtures: {[Chain in SupportedChains]?: any} = {
eth_testnet: {},
eth_mainnet: {},
extra_prop: {}
//~~~~~~~~~~ -> Type '{ eth_testnet: {}; eth_mainnet: {}; extra_prop: {}; }' is not assignable to...
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论