我如何Assert一个对象只具有来自TypeScript的字符串联合的属性?

aiqt4smr  于 2023-06-30  发布在  TypeScript
关注(0)|答案(2)|浏览(150)

下面是一个例子:

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 ??

我在??中尝试了以下操作:

  • 初始{ [chain: supportedChain]: any }-获取An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.ts(1337)
  • 接下来,{ [chain in supportedChain]: any }-这不会给予错误,但也不会防止不需要的 prop

不知道如何搜索这个,请建议如何实现这一点,最好是一些进一步的阅读。

6za6bjd0

6za6bjd01#

显式地设置类型,你的对象将受到保护,不受不需要的 prop 的影响。当使用as关键字时,你只是告诉编译器将对象视为与编译器推断的对象类型不同的类型。这被称为类型Assert。
现在你要使用的是Mapped Type。顾名思义,它将联合值Map为对象属性键。此外,您可以添加?以使属性成为可选的。(=> object仍然有效,如果不是所有的union值都作为属性存在)

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...
};
v8wbuo2f

v8wbuo2f2#

你应该使用satisfies操作符,另外添加constAssert会很好:

const fixtures = {
   eth_mainnet: 'some value',
   eth_testnet: 'some value 2',
} as const satisfies Record<supportedChains, string>

这种方法的好处是可以防止编译器扩大fixtures的类型。使用常规类型定义,fixtures的类型将是:Record<supportedChains, string,但是对于satisfiesconst assertion,它将从对象中获取精确的值:

{
   eth_mainnet: 'some value',
   eth_testnet: 'some value 2',
}

相关问题