Skip to content

Commit f0457ef

Browse files
committed
feat: improve strictObject to check for unexpected keys using a known keys set
1 parent ed6ec19 commit f0457ef

File tree

1 file changed

+27
-38
lines changed

1 file changed

+27
-38
lines changed

packages/internal/src/steps/strictObject/strictObject.ts

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export const strictObject = implStepPlugin<PluginDef>({
105105
// Pre-compute metadata for each property to avoid repeated lookups
106106
const keys = Object.keys(struct)
107107
const keysLen = keys.length
108+
const knownKeysSet = new Set(keys)
108109
const propsMeta: Array<{ key: string, isOptional: boolean, schema: Use<Valchecker> }> = []
109110

110111
for (let i = 0; i < keysLen; i++) {
@@ -131,7 +132,31 @@ export const strictObject = implStepPlugin<PluginDef>({
131132
})
132133
}
133134

134-
const ownKeysSet = new Set(Object.keys(value))
135+
// Check for unknown keys
136+
const ownKeys = Object.keys(value)
137+
const ownKeysLen = ownKeys.length
138+
const unknownKeys: string[] = []
139+
for (let i = 0; i < ownKeysLen; i++) {
140+
const key = ownKeys[i]!
141+
if (!knownKeysSet.has(key)) {
142+
unknownKeys.push(key)
143+
}
144+
}
145+
if (unknownKeys.length > 0) {
146+
return failure({
147+
code: 'strictObject:unexpected_keys',
148+
payload: { value, keys: unknownKeys },
149+
message: resolveMessage(
150+
{
151+
code: 'strictObject:unexpected_keys',
152+
payload: { value, keys: unknownKeys },
153+
},
154+
message,
155+
'Unexpected object keys found.',
156+
),
157+
})
158+
}
159+
135160
const issues: ExecutionIssue<any, any>[] = []
136161
const output: Record<string, any> = {}
137162

@@ -144,7 +169,6 @@ export const strictObject = implStepPlugin<PluginDef>({
144169
continue
145170
}
146171
const { key, isOptional, schema } = propsMeta[i]!
147-
ownKeysSet.delete(key)
148172
const propValue = (value as any)[key]
149173

150174
const propResult = (isOptional && propValue === void 0)
@@ -169,7 +193,6 @@ export const strictObject = implStepPlugin<PluginDef>({
169193
for (let j = i + 1; j < keysLen; j++) {
170194
const nextMeta = propsMeta[j]!
171195
const nextPropValue = (value as any)[nextMeta.key]
172-
ownKeysSet.delete(nextMeta.key)
173196

174197
chain = chain.then((): void | Promise<void> => {
175198
return Promise.resolve(
@@ -190,25 +213,7 @@ export const strictObject = implStepPlugin<PluginDef>({
190213
})
191214
}
192215

193-
return chain
194-
.then(() => {
195-
// Check for unexpected keys only if no issues so far
196-
if (issues.length === 0 && ownKeysSet.size > 0) {
197-
issues.push({
198-
code: 'strictObject:unexpected_keys',
199-
payload: { value, keys: Array.from(ownKeysSet) },
200-
message: resolveMessage(
201-
{
202-
code: 'strictObject:unexpected_keys',
203-
payload: { value, keys: Array.from(ownKeysSet) },
204-
},
205-
message,
206-
'Unexpected object keys found.',
207-
),
208-
})
209-
}
210-
})
211-
.then(() => issues.length > 0 ? failure(issues) : success(output))
216+
return chain.then(() => issues.length > 0 ? failure(issues) : success(output))
212217
}
213218

214219
if (isFailure(propResult)) {
@@ -221,22 +226,6 @@ export const strictObject = implStepPlugin<PluginDef>({
221226
}
222227
}
223228

224-
// Check for unexpected keys only if no issues so far
225-
if (issues.length === 0 && ownKeysSet.size > 0) {
226-
issues.push({
227-
code: 'strictObject:unexpected_keys',
228-
payload: { value, keys: Array.from(ownKeysSet) },
229-
message: resolveMessage(
230-
{
231-
code: 'strictObject:unexpected_keys',
232-
payload: { value, keys: Array.from(ownKeysSet) },
233-
},
234-
message,
235-
'Unexpected object keys found.',
236-
),
237-
})
238-
}
239-
240229
return issues.length > 0 ? failure(issues) : success(output)
241230
})
242231
},

0 commit comments

Comments
 (0)