如何使具有联合类型作为键的记录不对所有值强制执行?

huangapple go评论66阅读模式
英文:

How to make a Record with union type as key not mandatory for all values?

问题

在一个TypeScript项目中,我有一个类型中的一个封闭字符串属性:

type SubscriptionLevel = 'normal' | 'premium' | 'cancelled';

我想创建一个类似于映射的对象,使用这个类型作为键,但不是所有值都是必需的。

一个非常简单的例子是这样的:

const badgeIcon: Record<SubscriptionLevel, string | undefined> = {
    'premium': 'crown',
    'cancelled': 'grayed',
}

我只想为某些值指定映射值(这里我得到字符串,但实际代码将导致以不同方式渲染React组件)。

这段代码在运行时运行,但TypeScript会抱怨:“属性 'normal' 在类型 '{ premium: string; cancelled: string; }' 中丢失,但在类型 'Record<SubscriptionLevel, string | undefined>' 中是必需的。(2741)”。

我可以通过添加 'normal' 键来修复代码:

const badgeIcon: Record<SubscriptionLevel, string | undefined> = {
    'premium': 'crown',
    'cancelled': 'grayed',
    'normal': undefined
}

但这种方法需要是穷尽的,即使只有少数键需要有值(我的实际代码有10个键,但只有2个必须设置)。

所以我的问题是:有没有一种简单的方法来创建这个映射,其中的值是可选的?

类型安全很重要,所以我不想使用 'string' 作为键,因为它不会检查拼写错误。

英文:

In a typescript project, I have a closed string property in a type:

type SubscriptionLevel = &#39;normal&#39; | &#39;premium&#39; | &#39;cancelled&#39;;

I want to create a map-like object that use this type as a key, but not mandatory for all values.

A very simple example is this:

const badgeIcon : Record&lt;SubscriptionLevel, string | undefined&gt; = {
    &#39;premium&#39; : &#39;crown&#39;,
    &#39;cancelled&#39; : &#39;grayed&#39;,
}

I want, only for some of the values, to specify mapped values (here I get string but actual code will lead to rendering react component differently).

This code run at runtime but Typescript complains that Property &#39;normal&#39; is missing in type &#39;{ premium: string; cancelled: string; }&#39; but required in type &#39;Record&lt;SubscriptionLevel, string | undefined&gt;&#39;.(2741).

I can fix the code by adding also the normal key:

const badgeIcon : Record&lt;SubscriptionLevel, string | undefined&gt; = {
    &#39;premium&#39; : &#39;crown&#39;,
    &#39;cancelled&#39; : &#39;grayed&#39;,
    &#39;normal&#39;: undefined
}

But this approach requires to be exhaustive, even if only few kays should have a values (my actual code has 10 keys, but only 2 have to be set).

So my question is: is there any simple way to create this map, with optional values?

Type safety is important, so I don't want to use 'string' as key, because it won't check for typos.

答案1

得分: 2

你正在寻找内置的实用类型 Partial

type SubscriptionLevel = 'normal' | 'premium' | 'cancelled';

const badgeIcon: Partial<Record<SubscriptionLevel, string | undefined>> = {
  premium: 'crown',
  cancelled: 'grayed',
};
英文:

You are looking for built-in utility type Partial:

type SubscriptionLevel = &#39;normal&#39; | &#39;premium&#39; | &#39;cancelled&#39;;

const badgeIcon: Partial&lt;Record&lt;SubscriptionLevel, string | undefined&gt;&gt; = {
  premium: &#39;crown&#39;,
  cancelled: &#39;grayed&#39;,
};

huangapple
  • 本文由 发表于 2023年6月22日 15:38:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529580.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定