Company logo
  • Jobs
  • Bootcamp
  • About Us
  • For professionals
    • Home
    • Jobs
    • Courses
    • Questions
    • Teachers
    • Bootcamp
  • For business
    • Home
    • Our process
    • Plans
    • Assessments
    • Payroll
    • Blog
    • Calculator

0

42
Views
Typescript prevent generalization of string literal to type

So I have this constant Object

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",
  }
};

Now I want to infere the return type of each object based on its vr value, but if I look at typeof STUDY_TAGS all key-value pairs look the same like this:

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

Can I somehow force typescript to keep the string literals instead of generalizing them to the type string? I thought of defining the Object with the type Record<string, {tag: string, type: string, vr: "string" | "number"}> but then the all I get when looking at typeof STUDY_TAGS is

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

I am really lost here and have no idea on how to solve this problem. Shouldnt it somehow be possible to infer the return type based on an Object having one of 2 string values? In the end I want to create a function which takes in the object and know the returned type based on the vr value

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;
}
7 months ago · Juan Pablo Isaza
3 answers
Answer question

0

My main problem was not getting the type info from the object because it would generalize my string constants to the general type string although I defined my object with Object.freeze(). The solution was to define the object like so:

const obj = {a: {test: "hi"}} as const;
7 months ago · Juan Pablo Isaza Report

0

You should be able to declare the types '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",
  }
};

Above I've just added the 'as const' for the type property so you can see the difference. You can add these to any of the properties above to get the exact values rather than their primitive.

7 months ago · Juan Pablo Isaza Report

0

I believe function overloading and narrowing could help you. Here's a simplified example:

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

Then, when you call doSomething, TypeScript's typing system can infer the return type, because you told it whenever vr is equal to 'string', the function returns a string, and whenever vr is equal to 'number', the function returns a 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 with your specific use-case on TypeScript's playground.

7 months ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post job Plans Our process Sales
Legal
Terms and conditions Privacy policy
© 2023 PeakU Inc. All Rights Reserved.