使用if语句作为类型守卫,TypeScript未识别类型收窄
TypeScript无法识别
in操作符的类型收窄问题 用户定义的对象与函数代码:
const datas = { a: { "0": 0, "1": 1 }, b: { "0": 0 } } function index (data: keyof typeof datas, prop: "0"|"1") { if(prop in datas[data]) { return datas[data][prop] // <- 此处报错 } }
TypeScript抛出的错误:
Element implicitly has an 'any' type because expression of type "0" | "1" can't be used to index type '{ "0": number; "1": number; } | { "0": number; }'. Property '1' does not exist on type '{ "0": number; "1": number; } | { "0": number; }'.ts(7053)
尽管通过if(prop in datas[data])做了属性存在性检查,但TypeScript无法自动对联合类型进行收窄,导致报错。
解决方法
方案1:使用类型断言直接指定类型
既然已经通过in确认属性存在,可通过类型断言明确告诉TypeScript访问是安全的:
function index (data: keyof typeof datas, prop: "0"|"1") { if(prop in datas[data]) { return (datas[data] as Record<typeof prop, number>)[prop] } }
方案2:自定义类型守卫函数
编写专门的类型守卫,帮助TypeScript正确识别类型收窄逻辑:
type DataValue = typeof datas[keyof typeof datas]; function hasProp<T extends DataValue, K extends "0" | "1">(obj: T, prop: K): obj is T & Record<K, number> { return prop in obj; } function index (data: keyof typeof datas, prop: "0"|"1") { const target = datas[data]; if(hasProp(target, prop)) { return target[prop]; } }
方案3:重构数据类型定义
提前为datas定义更精确的类型,让TypeScript能更准确地推断参数与返回值类型:
type DataMap = { a: { "0": number; "1": number }, b: { "0": number } } const datas: DataMap = { a: { "0": 0, "1": 1 }, b: { "0": 0 } } function index<K extends keyof DataMap, P extends keyof DataMap[K]>(data: K, prop: P) { return datas[data][prop]; }
该方案还能限制函数参数的合法性,避免传入不存在的prop值。
内容的提问来源于stack exchange,提问作者Onii-Chan
相关产品推荐
相关产品推荐

