打字稿防止将字符串文字泛化为类型

Posted

技术标签:

【中文标题】打字稿防止将字符串文字泛化为类型【英文标题】: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;

【问题讨论】:

【参考方案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”,这样您就可以看到不同之处。您可以将这些添加到上面的任何属性中以获得确切的值而不是它们的原始值。

【讨论】:

以上是关于打字稿防止将字符串文字泛化为类型的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:允许泛型类型仅是具有“字符串”属性的对象

带有鸭子类型对象的打字稿字符串文字

如何在打字稿中迭代字符串文字类型

打字稿承诺泛型类型

打字稿:类型 ConstructorParameters 不接受泛型

接受通用参数和字符串数组的打字稿函数