Skip to content

fix: make behavior consistent for undefined nested fields and newer TS targets#15

Closed
dliv wants to merge 3 commits into
Twiddlle:mainfrom
dliv:dliv/optional-fields
Closed

fix: make behavior consistent for undefined nested fields and newer TS targets#15
dliv wants to merge 3 commits into
Twiddlle:mainfrom
dliv:dliv/optional-fields

Conversation

@dliv

@dliv dliv commented Apr 16, 2025

Copy link
Copy Markdown
Contributor

We encountered runtime errors when omitting a nested field. I'm not sure if the library intends to support optional nested fields or not.

If it does, the current code can throw if the consuming application's tsconfig has a newer target. The way uninitialized fields are treated is changing: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier .

The relevant lines are

for (const prop of props) {
// eslint-disable-next-line no-prototype-builtins
if (!entity.hasOwnProperty(prop.options.entityPropName)) {
continue;
}
if (prop.isNested) {
dbEntityData[prop.options.name] = this.normalizeProps(
entity[prop.options.entityPropName],

That config change affects whether an undefined value is enumerated on line 51, and then recursed on line 58, causing an NPE-like error on line 53.

Screenshot 2025-04-16 at 9 03 34 AM

To verify, you can change the target in your tsconfig to ES2022 and remove the application code tweak in this PR and the new unit test will fail. I'm not sure the fix in this PR is ideal, feel free to change / suggest-changes, but the new unit test demonstrates our current usage / config.

Comment on lines +118 to +130
// remove block in the future
// see: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier
{
const recentTsTarget = Object.keys(testingClass1).includes('nestedItem');
if (!recentTsTarget) {
console.debug('older TS target');
// make test object look like what newer TS targets generate
Object.assign(testingClass1, {
nestedItem: undefined,
nestedItems: undefined,
});
}
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely a hack. I thought about enabling the flag mentioned in those docs but it would probably be cleaner just to update the TS target. I'm not sure how extensive those changes would end up being or if you're interested in doing that. I might be able to help if you were.


if (prop.isNested) {
const value = entity[prop.options.entityPropName];
if (prop.isNested && value !== undefined && value !== null) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value !== null is scope creep not related to the TS config but it seems like a good / defensive idea. I'm fine backing that out.

@Twiddlle

Copy link
Copy Markdown
Owner

Reimplemted here #16

@Twiddlle Twiddlle closed this Apr 22, 2025
@Twiddlle

Copy link
Copy Markdown
Owner

@dliv dlivIf something is wrong, write it here pls. #17

@dliv

dliv commented Apr 22, 2025

Copy link
Copy Markdown
Contributor Author

That works for us. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants