mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Add an extra test for excess property check for intersection containing a recursive type (#53100)
This commit is contained in:
parent
74a37f8203
commit
615a97b1d4
@ -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'.
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
@ -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];
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user