diff --git a/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.errors.txt b/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.errors.txt new file mode 100644 index 00000000000..f4a1a0f7634 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.errors.txt @@ -0,0 +1,84 @@ +tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts(13,9): error TS2322: Type '{ l2: { type: "boolean"; }; invalid: false; }' is not assignable to type '{ l2: Schema1; }'. + Object literal may only specify known properties, and 'invalid' does not exist in type '{ l2: Schema1; }'. +tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts(26,9): error TS2322: Type '{ l2: { type: "boolean"; }; invalid: false; }' is not assignable to type '{ l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }'. + Object literal may only specify known properties, and 'invalid' does not exist in type '{ l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }'. +tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts(39,9): error TS2322: Type '{ l2: { type: "boolean"; }; invalid: false; }' is not assignable to type '{ l2: Schema3; }'. + Object literal may only specify known properties, and 'invalid' does not exist in type '{ l2: Schema3; }'. +tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts(52,9): error TS2322: Type '{ l2: { type: "boolean"; }; invalid: false; }' is not assignable to type 'Example<{ l2: boolean; }> & { l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }'. + Object literal may only specify known properties, and 'invalid' does not exist in type 'Example<{ l2: boolean; }> & { l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }'. + + +==== tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts (4 errors) ==== + // repro from #44750 + + type Request = { l1: { l2: boolean } }; + type Example = { ex?: T | null }; + + type Schema1 = (T extends boolean ? { type: 'boolean'; } : { props: { [P in keyof T]: Schema1 }; }) & Example; + + export const schemaObj1: Schema1 = { + props: { + l1: { + props: { + l2: { type: 'boolean' }, + invalid: false, + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ l2: { type: "boolean"; }; invalid: false; }' is not assignable to type '{ l2: Schema1; }'. +!!! error TS2322: Object literal may only specify known properties, and 'invalid' does not exist in type '{ l2: Schema1; }'. +!!! related TS6500 tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts:6:65: The expected type comes from property 'props' which is declared here on type 'Schema1<{ l2: boolean; }>' + }, + }, + }, + } + + type Schema2 = (T extends boolean ? { type: 'boolean'; } & Example : { props: { [P in keyof T]: Schema2 }; } & Example); + + export const schemaObj2: Schema2 = { + props: { + l1: { + props: { + l2: { type: 'boolean' }, + invalid: false, + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ l2: { type: "boolean"; }; invalid: false; }' is not assignable to type '{ l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }'. +!!! error TS2322: Object literal may only specify known properties, and 'invalid' does not exist in type '{ l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }'. +!!! related TS6500 tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts:19:78: The expected type comes from property 'props' which is declared here on type '{ props: { l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }; } & Example<{ l2: boolean; }>' + }, + }, + }, + } + + type Schema3 = Example & (T extends boolean ? { type: 'boolean'; } : { props: { [P in keyof T]: Schema3 }; }); + + export const schemaObj3: Schema3 = { + props: { + l1: { + props: { + l2: { type: 'boolean' }, + invalid: false, + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ l2: { type: "boolean"; }; invalid: false; }' is not assignable to type '{ l2: Schema3; }'. +!!! error TS2322: Object literal may only specify known properties, and 'invalid' does not exist in type '{ l2: Schema3; }'. +!!! related TS6500 tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts:32:78: The expected type comes from property 'props' which is declared here on type 'Schema3<{ l2: boolean; }>' + }, + }, + }, + } + + type Schema4 = (T extends boolean ? { type: 'boolean'; } & Example : { props: Example & { [P in keyof T]: Schema4 }; }); + + export const schemaObj4: Schema4 = { + props: { + l1: { + props: { + l2: { type: 'boolean' }, + invalid: false, + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ l2: { type: "boolean"; }; invalid: false; }' is not assignable to type 'Example<{ l2: boolean; }> & { l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }'. +!!! error TS2322: Object literal may only specify known properties, and 'invalid' does not exist in type 'Example<{ l2: boolean; }> & { l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }'. +!!! related TS6500 tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts:45:78: The expected type comes from property 'props' which is declared here on type '{ props: Example<{ l2: boolean; }> & { l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }; }' + }, + }, + }, + } + \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.symbols b/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.symbols new file mode 100644 index 00000000000..581bf89beeb --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.symbols @@ -0,0 +1,178 @@ +=== tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts === +// repro from #44750 + +type Request = { l1: { l2: boolean } }; +>Request : Symbol(Request, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 0, 0)) +>l1 : Symbol(l1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 16)) +>l2 : Symbol(l2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 22)) + +type Example = { ex?: T | null }; +>Example : Symbol(Example, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 39)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 3, 13)) +>ex : Symbol(ex, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 3, 19)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 3, 13)) + +type Schema1 = (T extends boolean ? { type: 'boolean'; } : { props: { [P in keyof T]: Schema1 }; }) & Example; +>Schema1 : Symbol(Schema1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 3, 36)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 13)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 13)) +>type : Symbol(type, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 40)) +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 63)) +>P : Symbol(P, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 74)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 13)) +>Schema1 : Symbol(Schema1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 3, 36)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 13)) +>P : Symbol(P, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 74)) +>Example : Symbol(Example, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 39)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 5, 13)) + +export const schemaObj1: Schema1 = { +>schemaObj1 : Symbol(schemaObj1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 7, 12)) +>Schema1 : Symbol(Schema1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 3, 36)) +>Request : Symbol(Request, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 0, 0)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 7, 45)) + + l1: { +>l1 : Symbol(l1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 8, 10)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 9, 9)) + + l2: { type: 'boolean' }, +>l2 : Symbol(l2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 10, 14)) +>type : Symbol(type, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 11, 13)) + + invalid: false, +>invalid : Symbol(invalid, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 11, 32)) + + }, + }, + }, +} + +type Schema2 = (T extends boolean ? { type: 'boolean'; } & Example : { props: { [P in keyof T]: Schema2 }; } & Example); +>Schema2 : Symbol(Schema2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 16, 1)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 13)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 13)) +>type : Symbol(type, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 40)) +>Example : Symbol(Example, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 39)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 13)) +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 76)) +>P : Symbol(P, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 87)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 13)) +>Schema2 : Symbol(Schema2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 16, 1)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 13)) +>P : Symbol(P, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 87)) +>Example : Symbol(Example, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 39)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 18, 13)) + +export const schemaObj2: Schema2 = { +>schemaObj2 : Symbol(schemaObj2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 20, 12)) +>Schema2 : Symbol(Schema2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 16, 1)) +>Request : Symbol(Request, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 0, 0)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 20, 45)) + + l1: { +>l1 : Symbol(l1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 21, 10)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 22, 9)) + + l2: { type: 'boolean' }, +>l2 : Symbol(l2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 23, 14)) +>type : Symbol(type, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 24, 13)) + + invalid: false, +>invalid : Symbol(invalid, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 24, 32)) + + }, + }, + }, +} + +type Schema3 = Example & (T extends boolean ? { type: 'boolean'; } : { props: { [P in keyof T]: Schema3 }; }); +>Schema3 : Symbol(Schema3, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 29, 1)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 13)) +>Example : Symbol(Example, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 39)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 13)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 13)) +>type : Symbol(type, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 53)) +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 76)) +>P : Symbol(P, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 87)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 13)) +>Schema3 : Symbol(Schema3, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 29, 1)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 13)) +>P : Symbol(P, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 31, 87)) + +export const schemaObj3: Schema3 = { +>schemaObj3 : Symbol(schemaObj3, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 33, 12)) +>Schema3 : Symbol(Schema3, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 29, 1)) +>Request : Symbol(Request, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 0, 0)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 33, 45)) + + l1: { +>l1 : Symbol(l1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 34, 10)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 35, 9)) + + l2: { type: 'boolean' }, +>l2 : Symbol(l2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 36, 14)) +>type : Symbol(type, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 37, 13)) + + invalid: false, +>invalid : Symbol(invalid, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 37, 32)) + + }, + }, + }, +} + +type Schema4 = (T extends boolean ? { type: 'boolean'; } & Example : { props: Example & { [P in keyof T]: Schema4 }; }); +>Schema4 : Symbol(Schema4, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 42, 1)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 13)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 13)) +>type : Symbol(type, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 40)) +>Example : Symbol(Example, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 39)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 13)) +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 76)) +>Example : Symbol(Example, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 2, 39)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 13)) +>P : Symbol(P, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 100)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 13)) +>Schema4 : Symbol(Schema4, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 42, 1)) +>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 13)) +>P : Symbol(P, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 44, 100)) + +export const schemaObj4: Schema4 = { +>schemaObj4 : Symbol(schemaObj4, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 46, 12)) +>Schema4 : Symbol(Schema4, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 42, 1)) +>Request : Symbol(Request, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 0, 0)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 46, 45)) + + l1: { +>l1 : Symbol(l1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 47, 10)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 48, 9)) + + l2: { type: 'boolean' }, +>l2 : Symbol(l2, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 49, 14)) +>type : Symbol(type, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 50, 13)) + + invalid: false, +>invalid : Symbol(invalid, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 50, 32)) + + }, + }, + }, +} + diff --git a/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.types b/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.types new file mode 100644 index 00000000000..77a7f341fed --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckIntersectionWithRecursiveType.types @@ -0,0 +1,157 @@ +=== tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts === +// repro from #44750 + +type Request = { l1: { l2: boolean } }; +>Request : { l1: { l2: boolean;}; } +>l1 : { l2: boolean; } +>l2 : boolean + +type Example = { ex?: T | null }; +>Example : Example +>ex : T | null | undefined +>null : null + +type Schema1 = (T extends boolean ? { type: 'boolean'; } : { props: { [P in keyof T]: Schema1 }; }) & Example; +>Schema1 : Schema1 +>type : "boolean" +>props : { [P in keyof T]: Schema1; } + +export const schemaObj1: Schema1 = { +>schemaObj1 : Schema1 +>{ props: { l1: { props: { l2: { type: 'boolean' }, invalid: false, }, }, },} : { props: { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; }; } + + props: { +>props : { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; } +>{ l1: { props: { l2: { type: 'boolean' }, invalid: false, }, }, } : { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; } + + l1: { +>l1 : { props: { l2: { type: "boolean"; }; invalid: boolean; }; } +>{ props: { l2: { type: 'boolean' }, invalid: false, }, } : { props: { l2: { type: "boolean"; }; invalid: boolean; }; } + + props: { +>props : { l2: { type: "boolean"; }; invalid: boolean; } +>{ l2: { type: 'boolean' }, invalid: false, } : { l2: { type: "boolean"; }; invalid: boolean; } + + l2: { type: 'boolean' }, +>l2 : { type: "boolean"; } +>{ type: 'boolean' } : { type: "boolean"; } +>type : "boolean" +>'boolean' : "boolean" + + invalid: false, +>invalid : boolean +>false : false + + }, + }, + }, +} + +type Schema2 = (T extends boolean ? { type: 'boolean'; } & Example : { props: { [P in keyof T]: Schema2 }; } & Example); +>Schema2 : Schema2 +>type : "boolean" +>props : { [P in keyof T]: Schema2; } + +export const schemaObj2: Schema2 = { +>schemaObj2 : { props: { l1: { props: { l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }; } & Example<{ l2: boolean; }>; }; } & Example +>{ props: { l1: { props: { l2: { type: 'boolean' }, invalid: false, }, }, },} : { props: { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; }; } + + props: { +>props : { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; } +>{ l1: { props: { l2: { type: 'boolean' }, invalid: false, }, }, } : { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; } + + l1: { +>l1 : { props: { l2: { type: "boolean"; }; invalid: boolean; }; } +>{ props: { l2: { type: 'boolean' }, invalid: false, }, } : { props: { l2: { type: "boolean"; }; invalid: boolean; }; } + + props: { +>props : { l2: { type: "boolean"; }; invalid: boolean; } +>{ l2: { type: 'boolean' }, invalid: false, } : { l2: { type: "boolean"; }; invalid: boolean; } + + l2: { type: 'boolean' }, +>l2 : { type: "boolean"; } +>{ type: 'boolean' } : { type: "boolean"; } +>type : "boolean" +>'boolean' : "boolean" + + invalid: false, +>invalid : boolean +>false : false + + }, + }, + }, +} + +type Schema3 = Example & (T extends boolean ? { type: 'boolean'; } : { props: { [P in keyof T]: Schema3 }; }); +>Schema3 : Schema3 +>type : "boolean" +>props : { [P in keyof T]: Schema3; } + +export const schemaObj3: Schema3 = { +>schemaObj3 : Schema3 +>{ props: { l1: { props: { l2: { type: 'boolean' }, invalid: false, }, }, },} : { props: { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; }; } + + props: { +>props : { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; } +>{ l1: { props: { l2: { type: 'boolean' }, invalid: false, }, }, } : { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; } + + l1: { +>l1 : { props: { l2: { type: "boolean"; }; invalid: boolean; }; } +>{ props: { l2: { type: 'boolean' }, invalid: false, }, } : { props: { l2: { type: "boolean"; }; invalid: boolean; }; } + + props: { +>props : { l2: { type: "boolean"; }; invalid: boolean; } +>{ l2: { type: 'boolean' }, invalid: false, } : { l2: { type: "boolean"; }; invalid: boolean; } + + l2: { type: 'boolean' }, +>l2 : { type: "boolean"; } +>{ type: 'boolean' } : { type: "boolean"; } +>type : "boolean" +>'boolean' : "boolean" + + invalid: false, +>invalid : boolean +>false : false + + }, + }, + }, +} + +type Schema4 = (T extends boolean ? { type: 'boolean'; } & Example : { props: Example & { [P in keyof T]: Schema4 }; }); +>Schema4 : Schema4 +>type : "boolean" +>props : Example & { [P in keyof T]: Schema4; } + +export const schemaObj4: Schema4 = { +>schemaObj4 : { props: Example & { l1: { props: Example<{ l2: boolean; }> & { l2: ({ type: "boolean"; } & Example) | ({ type: "boolean"; } & Example); }; }; }; } +>{ props: { l1: { props: { l2: { type: 'boolean' }, invalid: false, }, }, },} : { props: { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; }; } + + props: { +>props : { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; } +>{ l1: { props: { l2: { type: 'boolean' }, invalid: false, }, }, } : { l1: { props: { l2: { type: "boolean"; }; invalid: boolean; }; }; } + + l1: { +>l1 : { props: { l2: { type: "boolean"; }; invalid: boolean; }; } +>{ props: { l2: { type: 'boolean' }, invalid: false, }, } : { props: { l2: { type: "boolean"; }; invalid: boolean; }; } + + props: { +>props : { l2: { type: "boolean"; }; invalid: boolean; } +>{ l2: { type: 'boolean' }, invalid: false, } : { l2: { type: "boolean"; }; invalid: boolean; } + + l2: { type: 'boolean' }, +>l2 : { type: "boolean"; } +>{ type: 'boolean' } : { type: "boolean"; } +>type : "boolean" +>'boolean' : "boolean" + + invalid: false, +>invalid : boolean +>false : false + + }, + }, + }, +} + diff --git a/tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts b/tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts new file mode 100644 index 00000000000..187ed70e807 --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts @@ -0,0 +1,59 @@ +// @strict: true +// @noEmit: true + +// repro from #44750 + +type Request = { l1: { l2: boolean } }; +type Example = { ex?: T | null }; + +type Schema1 = (T extends boolean ? { type: 'boolean'; } : { props: { [P in keyof T]: Schema1 }; }) & Example; + +export const schemaObj1: Schema1 = { + props: { + l1: { + props: { + l2: { type: 'boolean' }, + invalid: false, + }, + }, + }, +} + +type Schema2 = (T extends boolean ? { type: 'boolean'; } & Example : { props: { [P in keyof T]: Schema2 }; } & Example); + +export const schemaObj2: Schema2 = { + props: { + l1: { + props: { + l2: { type: 'boolean' }, + invalid: false, + }, + }, + }, +} + +type Schema3 = Example & (T extends boolean ? { type: 'boolean'; } : { props: { [P in keyof T]: Schema3 }; }); + +export const schemaObj3: Schema3 = { + props: { + l1: { + props: { + l2: { type: 'boolean' }, + invalid: false, + }, + }, + }, +} + +type Schema4 = (T extends boolean ? { type: 'boolean'; } & Example : { props: Example & { [P in keyof T]: Schema4 }; }); + +export const schemaObj4: Schema4 = { + props: { + l1: { + props: { + l2: { type: 'boolean' }, + invalid: false, + }, + }, + }, +}