···6464 hasPatterns || (!!addPropsObj && (addPropsObj.type !== 'never' || !indexSchemas.length));
65656666 if (shouldCreateIndex) {
6767- // only inject additionalProperties when it's not "never"
6867 const addProps = addPropsObj;
6968 if (addProps && addProps.type !== 'never') {
7070- indexSchemas.unshift(addProps);
6969+ if (addProps.type === 'unknown') {
7070+ // When additionalProperties is unknown (e.g. `{}` or `true`), it already subsumes all
7171+ // named property types, so we only need the additionalProperties schema itself (plus any
7272+ // patternProperties) in the index signature. Including named property types would produce
7373+ // a redundant, noisy union like `unknown | string | null | ...`.
7474+ const patternSchemas: Array<IR.SchemaObject> = schema.patternProperties
7575+ ? Object.values(schema.patternProperties)
7676+ : [];
7777+ indexSchemas = [addProps, ...patternSchemas];
7878+ } else {
7979+ // For typed additionalProperties (e.g. `{ type: 'string' }`), named property types must
8080+ // be included so that TypeScript's index signature constraint is satisfied.
8181+ indexSchemas.unshift(addProps);
8282+ }
7183 } else if (!hasPatterns && !indexSchemas.length && addProps && addProps.type === 'never') {
7284 // keep "never" only when there are NO patterns and NO explicit properties
7385 indexSchemas = [addProps];
7486 }
75877676- if (hasOptionalProperties) {
8888+ // `unknown` already subsumes `undefined`, so no need to add it explicitly
8989+ if (hasOptionalProperties && addProps?.type !== 'unknown') {
7790 indexSchemas.push({ type: 'undefined' });
7891 }
7992