Add an extra test for excess property check for intersection containing a recursive type (#53100)

This commit is contained in:
Mateusz Burzyński 2023-03-08 21:34:47 +01:00 committed by GitHub
parent 74a37f8203
commit 615a97b1d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 328 additions and 1 deletions

View File

@ -6,9 +6,12 @@ tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts(39,9):
Object literal may only specify known properties, and 'invalid' does not exist in type '{ l2: Schema3<boolean>; }'.
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<false>) | ({ type: "boolean"; } & Example<true>); }'.
Object literal may only specify known properties, and 'invalid' does not exist in type 'Example<{ l2: boolean; }> & { l2: ({ type: "boolean"; } & Example<false>) | ({ type: "boolean"; } & Example<true>); }'.
tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts(86,11): error TS2322: Type '{ name: string; children: { name: string; children: { name: string; }[]; }[]; }' is not assignable to type 'User'.
Object literal may only specify known properties, and 'children' does not exist in type 'User'.
tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts(102,35): error TS2339: Property 'children' does not exist on type 'User'.
==== tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts (4 errors) ====
==== tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts (6 errors) ====
// repro from #44750
type Request = { l1: { l2: boolean } };
@ -81,4 +84,56 @@ tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts(52,9):
},
},
}
// repro from #40405
type Length<T extends any[]> = T["length"];
type Prepend<V, T extends any[]> = ((head: V, ...args: T) => void) extends (
...args: infer R
) => void
? R
: any;
type BuildTree<T, N extends number = -1, I extends any[] = []> = {
1: T;
0: T & { children: BuildTree<T, N, Prepend<any, I>>[] };
}[Length<I> extends N ? 1 : 0];
interface User {
name: string;
}
type GrandUser = BuildTree<User, 2>;
const grandUser: GrandUser = {
name: "Grand User",
children: [
{
name: "Son",
children: [
{
name: "Grand son",
children: [
~~~~~~~~
!!! error TS2322: Type '{ name: string; children: { name: string; children: { name: string; }[]; }[]; }' is not assignable to type 'User'.
!!! error TS2322: Object literal may only specify known properties, and 'children' does not exist in type 'User'.
{
name: "123",
children: [
{
name: "Some other name",
},
],
},
],
},
],
},
],
};
grandUser.children[0].children[0].children[0];
~~~~~~~~
!!! error TS2339: Property 'children' does not exist on type 'User'.

View File

@ -176,3 +176,115 @@ export const schemaObj4: Schema4<Request> = {
},
}
// repro from #40405
type Length<T extends any[]> = T["length"];
>Length : Symbol(Length, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 55, 1))
>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 59, 12))
>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 59, 12))
type Prepend<V, T extends any[]> = ((head: V, ...args: T) => void) extends (
>Prepend : Symbol(Prepend, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 59, 43))
>V : Symbol(V, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 60, 13))
>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 60, 15))
>head : Symbol(head, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 60, 37))
>V : Symbol(V, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 60, 13))
>args : Symbol(args, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 60, 45))
>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 60, 15))
...args: infer R
>args : Symbol(args, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 60, 76))
>R : Symbol(R, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 61, 16))
) => void
? R
>R : Symbol(R, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 61, 16))
: any;
type BuildTree<T, N extends number = -1, I extends any[] = []> = {
>BuildTree : Symbol(BuildTree, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 64, 8))
>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 15))
>N : Symbol(N, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 17))
>I : Symbol(I, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 40))
1: T;
>1 : Symbol(1, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 66))
>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 15))
0: T & { children: BuildTree<T, N, Prepend<any, I>>[] };
>0 : Symbol(0, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 67, 7))
>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 15))
>children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 68, 10))
>BuildTree : Symbol(BuildTree, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 64, 8))
>T : Symbol(T, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 15))
>N : Symbol(N, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 17))
>Prepend : Symbol(Prepend, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 59, 43))
>I : Symbol(I, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 40))
}[Length<I> extends N ? 1 : 0];
>Length : Symbol(Length, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 55, 1))
>I : Symbol(I, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 40))
>N : Symbol(N, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 66, 17))
interface User {
>User : Symbol(User, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 69, 31))
name: string;
>name : Symbol(User.name, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 71, 16))
}
type GrandUser = BuildTree<User, 2>;
>GrandUser : Symbol(GrandUser, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 73, 1))
>BuildTree : Symbol(BuildTree, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 64, 8))
>User : Symbol(User, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 69, 31))
const grandUser: GrandUser = {
>grandUser : Symbol(grandUser, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 77, 5))
>GrandUser : Symbol(GrandUser, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 73, 1))
name: "Grand User",
>name : Symbol(name, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 77, 30))
children: [
>children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 78, 21))
{
name: "Son",
>name : Symbol(name, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 80, 5))
children: [
>children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 81, 18))
{
name: "Grand son",
>name : Symbol(name, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 83, 9))
children: [
>children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 84, 28))
{
name: "123",
>name : Symbol(name, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 86, 13))
children: [
>children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 87, 26))
{
name: "Some other name",
>name : Symbol(name, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 89, 17))
},
],
},
],
},
],
},
],
};
grandUser.children[0].children[0].children[0];
>grandUser.children[0].children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 68, 10))
>grandUser.children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 68, 10))
>grandUser : Symbol(grandUser, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 77, 5))
>children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 68, 10))
>children : Symbol(children, Decl(excessPropertyCheckIntersectionWithRecursiveType.ts, 68, 10))

View File

@ -154,3 +154,116 @@ export const schemaObj4: Schema4<Request> = {
},
}
// repro from #40405
type Length<T extends any[]> = T["length"];
>Length : Length<T>
type Prepend<V, T extends any[]> = ((head: V, ...args: T) => void) extends (
>Prepend : [head: V, ...args: T]
>head : V
>args : T
...args: infer R
>args : R
) => void
? R
: any;
type BuildTree<T, N extends number = -1, I extends any[] = []> = {
>BuildTree : BuildTree<T, N, I>
>-1 : -1
>1 : 1
1: T;
>1 : T
0: T & { children: BuildTree<T, N, Prepend<any, I>>[] };
>0 : T & { children: BuildTree<T, N, Prepend<any, I>>[]; }
>children : BuildTree<T, N, [head: any, ...args: I]>[]
}[Length<I> extends N ? 1 : 0];
interface User {
name: string;
>name : string
}
type GrandUser = BuildTree<User, 2>;
>GrandUser : User & { children: (User & { children: User[]; })[]; }
const grandUser: GrandUser = {
>grandUser : User & { children: (User & { children: User[]; })[]; }
>{ name: "Grand User", children: [ { name: "Son", children: [ { name: "Grand son", children: [ { name: "123", children: [ { name: "Some other name", }, ], }, ], }, ], }, ],} : { name: string; children: { name: string; children: { name: string; children: { name: string; children: { name: string; }[]; }[]; }[]; }[]; }
name: "Grand User",
>name : string
>"Grand User" : "Grand User"
children: [
>children : { name: string; children: { name: string; children: { name: string; children: { name: string; }[]; }[]; }[]; }[]
>[ { name: "Son", children: [ { name: "Grand son", children: [ { name: "123", children: [ { name: "Some other name", }, ], }, ], }, ], }, ] : { name: string; children: { name: string; children: { name: string; children: { name: string; }[]; }[]; }[]; }[]
{
>{ name: "Son", children: [ { name: "Grand son", children: [ { name: "123", children: [ { name: "Some other name", }, ], }, ], }, ], } : { name: string; children: { name: string; children: { name: string; children: { name: string; }[]; }[]; }[]; }
name: "Son",
>name : string
>"Son" : "Son"
children: [
>children : { name: string; children: { name: string; children: { name: string; }[]; }[]; }[]
>[ { name: "Grand son", children: [ { name: "123", children: [ { name: "Some other name", }, ], }, ], }, ] : { name: string; children: { name: string; children: { name: string; }[]; }[]; }[]
{
>{ name: "Grand son", children: [ { name: "123", children: [ { name: "Some other name", }, ], }, ], } : { name: string; children: { name: string; children: { name: string; }[]; }[]; }
name: "Grand son",
>name : string
>"Grand son" : "Grand son"
children: [
>children : { name: string; children: { name: string; }[]; }[]
>[ { name: "123", children: [ { name: "Some other name", }, ], }, ] : { name: string; children: { name: string; }[]; }[]
{
>{ name: "123", children: [ { name: "Some other name", }, ], } : { name: string; children: { name: string; }[]; }
name: "123",
>name : string
>"123" : "123"
children: [
>children : { name: string; }[]
>[ { name: "Some other name", }, ] : { name: string; }[]
{
>{ name: "Some other name", } : { name: string; }
name: "Some other name",
>name : string
>"Some other name" : "Some other name"
},
],
},
],
},
],
},
],
};
grandUser.children[0].children[0].children[0];
>grandUser.children[0].children[0].children[0] : any
>grandUser.children[0].children[0].children : any
>grandUser.children[0].children[0] : User
>grandUser.children[0].children : User[]
>grandUser.children[0] : User & { children: User[]; }
>grandUser.children : (User & { children: User[]; })[]
>grandUser : User & { children: (User & { children: User[]; })[]; }
>children : (User & { children: User[]; })[]
>0 : 0
>children : User[]
>0 : 0
>children : any
>0 : 0

View File

@ -57,3 +57,50 @@ export const schemaObj4: Schema4<Request> = {
},
},
}
// repro from #40405
type Length<T extends any[]> = T["length"];
type Prepend<V, T extends any[]> = ((head: V, ...args: T) => void) extends (
...args: infer R
) => void
? R
: any;
type BuildTree<T, N extends number = -1, I extends any[] = []> = {
1: T;
0: T & { children: BuildTree<T, N, Prepend<any, I>>[] };
}[Length<I> extends N ? 1 : 0];
interface User {
name: string;
}
type GrandUser = BuildTree<User, 2>;
const grandUser: GrandUser = {
name: "Grand User",
children: [
{
name: "Son",
children: [
{
name: "Grand son",
children: [
{
name: "123",
children: [
{
name: "Some other name",
},
],
},
],
},
],
},
],
};
grandUser.children[0].children[0].children[0];