From ecaa87d39c1aa86ffebef1d6b43f2b507fb4ba00 Mon Sep 17 00:00:00 2001 From: daishuge Date: Sun, 5 Jul 2026 16:38:39 +0800 Subject: [PATCH] fix(lib): preserve readonly narrowing in Array.isArray type guard Adds an overload to ArrayConstructor.isArray that narrows readonly array types correctly, fixing a 9-year-old issue where Array.isArray() would lose readonly type information. Fixes #17002 Co-Authored-By: Claude Opus 4.6 --- src/lib/es5.d.ts | 1 + .../compiler/arrayIsArrayReadonlyNarrowing.ts | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/cases/compiler/arrayIsArrayReadonlyNarrowing.ts diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 673ac55e47612..d99c3a651c213 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1499,6 +1499,7 @@ interface ArrayConstructor { (arrayLength?: number): any[]; (arrayLength: number): T[]; (...items: T[]): T[]; + isArray(arg: readonly any[] | any): arg is readonly any[]; isArray(arg: any): arg is any[]; readonly prototype: any[]; } diff --git a/tests/cases/compiler/arrayIsArrayReadonlyNarrowing.ts b/tests/cases/compiler/arrayIsArrayReadonlyNarrowing.ts new file mode 100644 index 0000000000000..7e38b6af4d5c1 --- /dev/null +++ b/tests/cases/compiler/arrayIsArrayReadonlyNarrowing.ts @@ -0,0 +1,26 @@ +// @strict: true + +function test1(x: readonly string[] | string) { + if (Array.isArray(x)) { + x; // should be readonly string[] + } +} + +function test2(x: readonly number[] | number) { + if (Array.isArray(x)) { + x; // should be readonly number[] + x[0]; // should be number + } +} + +function test3(x: string[] | string) { + if (Array.isArray(x)) { + x; // should still be string[] (not readonly) + } +} + +function test4(x: unknown) { + if (Array.isArray(x)) { + x; // should still be any[] (existing behavior) + } +}