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;
}
CodePudding user response:
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.
CodePudding user response:
Thanks for the attempt at helping. 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;
I did not find this in the Typescript documentation, so I spent some unneeded hours on this problem. With this solution the rest was easy enough.
CodePudding user response:
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.