Typescript 未对对象数组强制实施区分类型

Typescript not enforcing discriminated type on array of objects

提问人:kael 提问时间:7/11/2023 更新时间:7/11/2023 访问量:34

问:

我创建了以下一组类型(简化):

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];
};

鉴于上述类型,我希望能够将多个对象分配给一个数组,并让打字稿强制执行其参数。但是,它似乎将参数解释为所有可能的参数的并集,而不是与给定的特定 ID 关联的参数。PrevalConfig

例如,以下内容应引发错误,但不会:

const prevals: PrevalConfig<Prevals>[] = [
  {
    id: Prevals.one,
    level: 'warning',
    params: {
      t: 'thing'
    }
  }
]

我相信这是因为该类型本质上是“PrevalConfig 对象的数组,其中参数是所有可能的 Prevals 的并集”。鉴于这种解释,从技术上讲,它键入“所有可能的参数的并集”是正确的。然而,这不是我想要的。PrevalConfig<Prevals>[]Idparams

我该如何完成这项工作?

(这是一个预装了所有这些的游乐场)

打字稿 可区分并集

评论


答:

0赞 kael 7/11/2023 #1

我的一个同事刚刚帮我解决了这个问题。我一直对自己说,“我需要成为所有可能的 preval 配置的并集,而不是参数化类型”,确实有一个(有点奇怪的)打字稿结构:PrevalConfig

type PrevalConfig = {
  [Id in Prevals]: {
    id: Id;
    level: 'error' | 'warning';
    params: PrevalParams[Id];
  };
}[Prevals];

基本上,您可以创建每个 preval 的映射类型,以匹配其特定类型的配置。然后,您同时告诉打字稿为您提供该映射类型的所有值的并集。因此,您:D拥有所有可能的 preval 配置的并集。

谢谢,匿名同事!

评论

0赞 jcalz 7/11/2023
这种数据结构被称为“分布式对象类型”,正如 GitHub 问题 microsoft/typescript#47109 中创造的那样(在移动设备上,现在很难添加链接,也许我稍后会把它放在这里
0赞 kael 7/12/2023
啊!@jcalz,谢谢你的参考。