TypeScript如何避免对象属性字符串字面量被拓宽为string类型
解决方案
1. 保留字面量类型避免拓宽
默认情况下TypeScript推导普通const对象的属性时,会将字符串/数字值拓宽为对应的基础类型(比如"string"字面量拓宽为string类型),要保留精确的字面量类型,直接给整个对象加as const断言即可:
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", } } as const;
此时typeof STUDY_TAGS会保留每个属性的精确字面量类型,比如InstanceAvailability.vr的类型是"string",NumberofStudyRelatedSeries.vr的类型是"number",不会被统一拓宽。
2. 同时增加类型校验不丢失精度
如果你需要约束对象的结构(比如限制vr只能是"string"/"number",type只能是"required"/"optional"),不要直接用Record做类型注解,这会抹掉每个字段的独立类型信息,改用TS 4.9以上支持的satisfies操作符,同时满足类型校验和保留字面量的需求:
// 先定义结构约束 type StudyTagMeta = { tag: string; type: "optional" | "required"; vr: "string" | "number"; } 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", } } as const satisfies Record<string, StudyTagMeta>;
如果对象属性不符合StudyTagMeta的约束,TS会直接抛出错误,同时不会丢失每个字段的字面量类型。
3. 函数调用效果
你定义的doSomething函数本身逻辑是正确的,配合上面处理后的STUDY_TAGS,就能自动根据入参的vr值推导返回类型:
// 返回值类型自动推导为string const res1 = doSomething(STUDY_TAGS.InstanceAvailability); // 返回值类型自动推导为number const res2 = doSomething(STUDY_TAGS.NumberofStudyRelatedSeries);
低版本TS兼容方案
如果你的TS版本低于4.9不支持satisfies,可以用泛型工具函数实现同样的效果:
type StudyTagMeta = { tag: string; type: "optional" | "required"; vr: "string" | "number"; } function defineStudyTags<T extends Record<string, StudyTagMeta>>(tags: T) { return tags; } const STUDY_TAGS = defineStudyTags({ 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", } });
内容的提问来源于stack exchange,提问作者Niclas do
相关产品推荐
相关产品推荐

