英文:
Typescript not enforcing discriminated type on array of objects
问题
以下是翻译好的代码部分:
enum Prevals {
one = 'one',
two = 'two',
three = 'three',
}
type PrevalParams = {
[Prevals.one]: {
name: string;
age: number;
};
[Prevals.two]: {
t: 'thing';
};
[Prevals.three]: undefined;
}
type PrevalConfig<Id extends Prevals> = {
id: Id;
level: 'error' | 'warning';
params: PrevalParams[Id];
};
const prevals: PrevalConfig<Prevals>[] = [
{
id: Prevals.one,
level: 'warning',
params: {
t: 'thing'
}
}
]
请注意,翻译后的代码与原始代码相同,只是去除了HTML编码和注释。
英文:
I've created the following set of types (simplified):
enum Prevals {
one = 'one',
two = 'two',
three = 'three',
}
type PrevalParams = {
[Prevals.one]: {
name: string;
age: number;
};
[Prevals.two]: {
t: 'thing';
};
[Prevals.three]: undefined;
}
type PrevalConfig<Id extends Prevals> = {
id: Id;
level: 'error' | 'warning';
params: PrevalParams[Id];
};
Given the above types, I would expect to be able to assign several PrevalConfig
objects to an array and have typescript enforce their parameters. However, it seems to interpret the params as the union of all possible params, rather than as the params associated with the specific ID given.
For example, the following should throw an error but doesn't:
const prevals: PrevalConfig<Prevals>[] = [
{
id: Prevals.one,
level: 'warning',
params: {
t: 'thing'
}
}
]
I believe this is because the type PrevalConfig<Prevals>[]
essentially says "an array of PrevalConfig objects where the Id
parameter is the union of all possible Prevals." Given that interpretation, it is technically correct that it types the params
as "the union of all possible params". However, that's not what I want.
How do I make this work?
(here's a playground with all this pre-loaded)
答案1
得分: 0
同事帮助我解决了这个问题。我一直在对自己说:“我需要`PrevalConfig`成为所有可能的预值配置的并集,而不是参数化类型”,确实有一个(有点奇怪的)typescript 构造用于此:
```typescript
type PrevalConfig = {
[Id in Prevals]: {
id: Id;
level: 'error' | 'warning';
params: PrevalParams[Id];
};
}[Prevals];
基本上,你创建了每个预值到其具体类型的映射类型。然后在同一个动作中,你告诉typescript给你该映射类型的所有值的并集。因此,你就拥有了所有可能的预值配置的并集:D。
感谢,匿名同事!
<details>
<summary>英文:</summary>
A colleague of mine just helped me work this one out. I kept saying to myself, "I need `PrevalConfig` to be the union of all possible preval configs, not a parameterized type," and indeed there's a (somewhat weird) typescript construct for that:
```typescript
type PrevalConfig = {
[Id in Prevals]: {
id: Id;
level: 'error' | 'warning';
params: PrevalParams[Id];
};
}[Prevals];
Basically, you create a mapped type of each preval to it's specifically-typed config. Then in the same swoop, you tell typescript to give you the union of all of the values for that mapped type. Thus, you have the union of all possible preval configs :D.
Thanks, anonymous colleague!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论