Skip to content

Commit

Permalink
Types that extend Array or ReadonlyArray are automatically array-like
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbranch committed Mar 15, 2021
1 parent 322c70f commit 684b039
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19703,7 +19703,13 @@ namespace ts {
function isArrayLikeType(type: Type): boolean {
// A type is array-like if it is a reference to the global Array or global ReadonlyArray type,
// or if it is not the undefined or null type and if it is assignable to ReadonlyArray<any>
return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
return isArrayType(type) || hasArrayOrReadonlyArrayBaseType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
}

function hasArrayOrReadonlyArrayBaseType(type: Type): boolean {
return !!(getObjectFlags(type) & ObjectFlags.Reference)
&& !!(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)
&& some(getBaseTypes((type as TypeReference).target as InterfaceType), isArrayType);
}

function isEmptyArrayLiteralType(type: Type): boolean {
Expand Down
19 changes: 19 additions & 0 deletions tests/baselines/reference/excessiveStackDepthFlatArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//// [excessiveStackDepthFlatArray.ts]
interface MiddlewareArray<T> extends Array<T> {}
declare function configureStore(options: { middleware: MiddlewareArray<any> }): void;

declare const defaultMiddleware: MiddlewareArray<any>;
configureStore({
middleware: [...defaultMiddleware], // Should not error
});


//// [excessiveStackDepthFlatArray.js]
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
configureStore({
middleware: __spreadArray([], defaultMiddleware)
});
26 changes: 26 additions & 0 deletions tests/baselines/reference/excessiveStackDepthFlatArray.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
=== tests/cases/compiler/excessiveStackDepthFlatArray.ts ===
interface MiddlewareArray<T> extends Array<T> {}
>MiddlewareArray : Symbol(MiddlewareArray, Decl(excessiveStackDepthFlatArray.ts, 0, 0))
>T : Symbol(T, Decl(excessiveStackDepthFlatArray.ts, 0, 26))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more)
>T : Symbol(T, Decl(excessiveStackDepthFlatArray.ts, 0, 26))

declare function configureStore(options: { middleware: MiddlewareArray<any> }): void;
>configureStore : Symbol(configureStore, Decl(excessiveStackDepthFlatArray.ts, 0, 48))
>options : Symbol(options, Decl(excessiveStackDepthFlatArray.ts, 1, 32))
>middleware : Symbol(middleware, Decl(excessiveStackDepthFlatArray.ts, 1, 42))
>MiddlewareArray : Symbol(MiddlewareArray, Decl(excessiveStackDepthFlatArray.ts, 0, 0))

declare const defaultMiddleware: MiddlewareArray<any>;
>defaultMiddleware : Symbol(defaultMiddleware, Decl(excessiveStackDepthFlatArray.ts, 3, 13))
>MiddlewareArray : Symbol(MiddlewareArray, Decl(excessiveStackDepthFlatArray.ts, 0, 0))

configureStore({
>configureStore : Symbol(configureStore, Decl(excessiveStackDepthFlatArray.ts, 0, 48))

middleware: [...defaultMiddleware], // Should not error
>middleware : Symbol(middleware, Decl(excessiveStackDepthFlatArray.ts, 4, 16))
>defaultMiddleware : Symbol(defaultMiddleware, Decl(excessiveStackDepthFlatArray.ts, 3, 13))

});

23 changes: 23 additions & 0 deletions tests/baselines/reference/excessiveStackDepthFlatArray.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
=== tests/cases/compiler/excessiveStackDepthFlatArray.ts ===
interface MiddlewareArray<T> extends Array<T> {}
declare function configureStore(options: { middleware: MiddlewareArray<any> }): void;
>configureStore : (options: { middleware: MiddlewareArray<any>;}) => void
>options : { middleware: MiddlewareArray<any>; }
>middleware : MiddlewareArray<any>

declare const defaultMiddleware: MiddlewareArray<any>;
>defaultMiddleware : MiddlewareArray<any>

configureStore({
>configureStore({ middleware: [...defaultMiddleware], // Should not error}) : void
>configureStore : (options: { middleware: MiddlewareArray<any>; }) => void
>{ middleware: [...defaultMiddleware], // Should not error} : { middleware: any[]; }

middleware: [...defaultMiddleware], // Should not error
>middleware : any[]
>[...defaultMiddleware] : any[]
>...defaultMiddleware : any
>defaultMiddleware : MiddlewareArray<any>

});

9 changes: 9 additions & 0 deletions tests/cases/compiler/excessiveStackDepthFlatArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @lib: es2019

interface MiddlewareArray<T> extends Array<T> {}
declare function configureStore(options: { middleware: MiddlewareArray<any> }): void;

declare const defaultMiddleware: MiddlewareArray<any>;
configureStore({
middleware: [...defaultMiddleware], // Should not error
});

0 comments on commit 684b039

Please sign in to comment.