显式对象键与string类型场景下TypeScript类型收窄失效问题
解决TypeScript中
hasOwnProperty无法收窄类型的问题 针对你遇到的场景,以下几种方法可以实现有效的类型收窄:
方法一:自定义类型守卫(推荐)
通过类型谓词创建自定义类型守卫函数,明确判断键是否属于目标对象的键类型:
export const PRISMA_TYPES_TO_TS = { 'Int': 'number', 'BigInt': 'number', 'Decimal': 'number', 'Float': 'number', 'String': 'string', 'Bytes': 'string', 'Boolean': 'boolean', 'DateTime': 'Date', } as const; // 提取对象的键类型为联合字面量类型 type PrismaTypeKey = keyof typeof PRISMA_TYPES_TO_TS; // 自定义类型守卫,判断输入是否为合法键 function isPrismaTypeKey(key: string): key is PrismaTypeKey { return key in PRISMA_TYPES_TO_TS; } const randomKey: string = "randomKey"; if (isPrismaTypeKey(randomKey)) { // randomKey被自动收窄为PrismaTypeKey,访问属性无TS错误 console.log('type is good', PRISMA_TYPES_TO_TS[randomKey]); } else { console.log('value is not good'); }
优点:保留了对象的精确类型,类型安全且语义清晰。
方法二:结合Object.keys与类型断言
先将对象的键转为合法键的数组,再判断目标字符串是否在其中:
export const PRISMA_TYPES_TO_TS = { 'Int': 'number', 'BigInt': 'number', 'Decimal': 'number', 'Float': 'number', 'String': 'string', 'Bytes': 'string', 'Boolean': 'boolean', 'DateTime': 'Date', } as const; type PrismaTypeKey = keyof typeof PRISMA_TYPES_TO_TS; const randomKey: string = "randomKey"; // 将Object.keys的结果断言为合法键数组,再进行包含判断 if ((Object.keys(PRISMA_TYPES_TO_TS) as PrismaTypeKey[]).includes(randomKey as PrismaTypeKey)) { console.log('type is good', PRISMA_TYPES_TO_TS[randomKey as PrismaTypeKey]); } else { console.log('value is not good'); }
优点:无需额外定义函数,适合简单场景;缺点:需要手动添加类型断言,代码稍显繁琐。
方法三:添加索引签名(不推荐)
给对象添加字符串索引签名,放宽类型约束,让TS允许用任意字符串访问属性:
export const PRISMA_TYPES_TO_TS: { [key: string]: string } = { 'Int': 'number', 'BigInt': 'number', 'Decimal': 'number', 'Float': 'number', 'String': 'string', 'Bytes': 'string', 'Boolean': 'boolean', 'DateTime': 'Date', }; const randomKey: string = "randomKey"; if (PRISMA_TYPES_TO_TS.hasOwnProperty(randomKey)) { console.log('type is good', PRISMA_TYPES_TO_TS[randomKey]); } else { console.log('value is not good'); }
缺点:丢失了对象键的精确字面量类型,无法再对非法键进行编译时检查,仅适合对类型精度要求不高的场景。
内容的提问来源于stack exchange,提问作者eugenedrvnk
相关产品推荐
相关产品推荐

