【问题标题】:Typescript prevent generalization of string literal to type打字稿防止将字符串文字泛化为类型
【发布时间】:2021-12-10 21:55:00
【问题描述】:

所以我有这个常量对象

const STUDY_TAGS ={
  InstanceAvailability: { tag: "00080056", type: "optional", vr: "string" },
  ModalitiesinStudy: { tag: "00080061", type: "required", vr: "string" },
  ReferringPhysiciansName: { tag: "00080090", type: "required", vr: "string" },
  NumberofStudyRelatedSeries: {
    tag: "00201206",
    type: "required",
    vr: "number",
  }
};

现在我想根据其 vr 值推断每个对象的返回类型,但如果我查看 typeof STUDY_TAGS 所有键值对看起来都像这样:

 InstanceAvailability: {
        tag: string;
        type: string;
        vr: string;
    };

我可以以某种方式强制打字稿保留字符串文字而不是将它们概括为类型字符串吗? 我想用 Record 但是我在查看 typeof STUDY_TAGS 时得到的只是

Record<string, {
    tag: string;
    type: string;
    vr: "string" | "number";
}

我真的迷路了,不知道如何解决这个问题。不应该以某种方式根据具有 2 个字符串值之一的 Object 推断返回类型吗? 最后我想创建一个函数,它接受对象并根据 vr 值知道返回的类型

function doSomething<Type extends "number" | "string">({tag, type, vr} : {tag : string, type : string, vr: Type}) : Type extends "number" ? number : string
{
 if(vr === "string") return "test";
 return 0;
}

【问题讨论】:

    标签: javascript typescript types


    【解决方案1】:

    我相信函数重载和缩小可以帮助你。这是一个简化的示例:

    function doSomething(vr: 'string'): string
    function doSomething(vr: 'number'): number
    function doSomething(vr: string): string | number {
      if(vr === 'string) return 'Test!';
      return 0;
    }
    

    然后,当你调用doSomething 时,TypeScript 的打字系统可以推断出返回类型,因为你告诉它只要vr 等于'string',函数就会返回一个字符串,并且只要vr 等于'number',函数返回一个数字。

    const foo = doSomething('string'); // TypeScript knows 'foo' is a string
    const bar = doSomething(2); // TypeScript know 'bar' is a number
    

    Here is a more complete example 与您在 TypeScript 的操场上的特定用例。

    【讨论】:

      【解决方案2】:

      我的主要问题是没有从对象中获取类型信息,因为尽管我使用Object.freeze() 定义了我的对象,但它会将我的字符串常量概括为一般类型字符串。解决方案是像这样定义对象:

      const obj = {a: {test: "hi"}} as const;
      

      【讨论】:

      • 这几乎是评论而不是答案,它看起来与@Tom 的答案几乎相同。我意识到新用户无法发表评论,但接受/赞成他的答案而不是发布评论性答案是礼貌的。
      • 我在汤姆写评论之前写了答案,这就是为什么我没有选择他的答案。否则他的评论将正是我想要的。
      • 那么应该支持他的回答——它正好解决了你的问题。
      【解决方案3】:

      您应该能够将类型声明为 'as const'

      const STUDY_TAGS ={
        InstanceAvailability: { tag: "00080056", type: "optional" as const, vr: "string" },
        ModalitiesinStudy: { tag: "00080061", type: "required" as const, vr: "string" },
        ReferringPhysiciansName: { tag: "00080090", type: "required" as const, vr: "string" },
        NumberofStudyRelatedSeries: {
          tag: "00201206",
          type: "required" as const,
          vr: "number",
        }
      };
      

      上面我刚刚为type 属性添加了“as const”,这样您就可以看到不同之处。您可以将这些添加到上面的任何属性中以获得确切的值而不是它们的原始值。

      【讨论】:

        猜你喜欢
        • 2020-10-16
        • 2018-04-28
        • 2021-11-26
        • 2019-10-15
        • 2021-04-20
        • 2023-01-04
        • 2019-06-05
        • 2015-11-27
        • 2021-12-05
        相关资源
        最近更新 更多