如何在TypeScript中不创建实例检查自定义类型是否含指定属性?
解决方案:在运行时验证TypeScript类型的合法属性
TypeScript的类型是编译时概念,编译后会被完全擦除,所以你没法直接通过if (userInput.key in Person)这种方式验证——因为运行时根本不存在Person这个实体。要实现需求,你需要把类型的键信息同步到运行时的变量中,用这个变量做验证依据,同时保证类型和运行时数据的一致性。
步骤1:维护运行时的合法键集合
先创建一个包含Person所有合法属性的只读数组,用as const固定它的类型,这样后续可以基于这个数组推导Person类型,避免重复维护:
// 运行时的合法键集合,改这里就同步更新类型 const PERSON_KEYS = ['name', 'age'] as const; // 基于键集合推导Person的键类型 type PersonKey = typeof PERSON_KEYS[number]; // 基于键类型定义Person类型 type Person = { [K in PersonKey]: K extends 'name' ? string : number; };
步骤2:编写类型安全的验证函数
写一个断言函数,检查输入的key是否属于合法集合,同时让TypeScript能识别验证后的类型:
function isValidPersonKey(key: string): key is PersonKey { // 把只读数组转成string[]后用includes做检查 return (PERSON_KEYS as readonly string[]).includes(key); }
步骤3:验证用户输入并执行更新
现在就可以用这个函数验证用户输入,合法时安全更新Person对象,非法时处理错误:
// 合法输入示例 const userInput = { key: "name", value: "ari" }; // 非法输入示例(取消注释测试) // const userInput = { key: "job", value: "milk man" }; if (isValidPersonKey(userInput.key)) { // 这里TypeScript会自动推断userInput.key是Person的合法键 const person: Person = { name: "", age: 0 }; // 类型断言确保值的类型匹配 person[userInput.key] = userInput.value as Person[PersonKey]; console.log("更新成功:", person); } else { console.error(`非法属性:${userInput.key},仅允许${PERSON_KEYS.join(', ')}`); }
为什么不能直接用in Person?
TypeScript在编译后会移除所有类型相关代码,运行时只有JavaScript逻辑。Person作为类型,编译后完全不存在,自然没法用in操作符检查。通过维护运行时键集合,相当于把编译时的类型信息“带到”了运行时,既保证类型安全,又能做合法性验证。
内容的提问来源于stack exchange,提问作者Ari
相关产品推荐
相关产品推荐

