TypeScript字符串插值读取已定义对象属性返回undefined问题求解
可能引发该问题的常见场景
- 属性名拼写/大小写错误
直接访问属性时如果使用的是复制的正确属性名可以正常返回值,但模板插值时如果手动输入时拼错了属性名(比如将atrrError误写为attrError、大小写不匹配),就会返回undefined。
排查方法:将模板插值中的属性名和直接打印时的属性名逐字符比对,确认完全一致。 - TypeScript编译配置
useDefineForClassFields导致的访问器异常
你使用的TypeScript 4.4版本对类字段的默认处理逻辑和ES原生标准存在差异,如果tsconfig.json中开启了useDefineForClassFields: true,会导致类的访问器(get/set)和声明的私有字段冲突,编译后的JS代码会直接在实例上挂载值为undefined的同名字段,覆盖原型上的getter逻辑。部分场景下直接访问时会命中原型的getter返回正确值,模板插值时却读取到实例上的undefined字段。
排查方法:检查tsconfig.json的compilerOptions配置,关闭useDefineForClassFields后重新运行测试。 - 模板字符串提前初始化而非动态生成
如果你的SQL拼接模板定义在TestObject类的静态属性、模块顶层等提前执行的位置,而非insert_data方法执行时才动态生成,那么模板插值的求值时机远早于TestObject实例的属性赋值阶段,此时读取的属性自然为undefined。
排查方法:确认SQL模板字符串的定义位置,确保是在insert_data方法内部、testObject属性赋值完成后才执行插值逻辑。 - 实例被Proxy代理导致的访问逻辑差异
如果你使用的ORM框架、状态管理库自动给TestObject实例套了Proxy代理,代理的get捕获器可能对不同的访问场景做了区分处理:直接属性访问时返回缓存的正确值,模板插值内部的隐式取值操作触发了异常分支返回undefined。
排查方法:通过console.log(testObject instanceof TestObject)验证实例是否是原始类的实例,也可以通过Object.assign({}, testObject)拷贝所有可枚举属性后再做插值测试。 - Getter内部存在隐式分支判断
如果你为atrrError定义的getter内部存在依赖运行时上下文的判断逻辑(比如判断调用栈、判断this的指向、依赖某个外部状态变量),可能出现直接访问时走正确分支返回值,模板插值时走异常分支返回undefined的情况。
排查方法:在getter内部加日志打印返回值,确认插值时getter是否被调用、返回值是否正确。 - ts-node缓存编译产物导致的代码不一致
ts-node默认会缓存编译后的JS文件,如果你修改了TestObject类的属性定义后没有清空缓存直接运行,会出现运行时代码和源码不一致的情况,导致属性访问出现异常。
排查方法:运行ts-node --cache-clean启动项目,或者手动删除node_modules/.cache/ts-node目录后重新测试。
内容的提问来源于stack exchange,提问作者WorrenGilgamesh
相关产品推荐
相关产品推荐

