From ef70c04f35762d20d277935b56bfd0405613d4a7 Mon Sep 17 00:00:00 2001 From: Ulrich Buchgraber Date: Sat, 8 Dec 2018 02:18:01 +0100 Subject: [PATCH 1/6] Add ReadonlyArray overload for Array.isArray() --- src/lib/es5.d.ts | 1 + tests/baselines/reference/isArray.errors.txt | 71 ++++++++ tests/baselines/reference/isArray.js | 87 +++++++++- tests/baselines/reference/isArray.symbols | 132 +++++++++++++- tests/baselines/reference/isArray.types | 173 +++++++++++++++++-- tests/cases/compiler/isArray.ts | 50 +++++- 6 files changed, 486 insertions(+), 28 deletions(-) create mode 100644 tests/baselines/reference/isArray.errors.txt diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index c8e99f0d1dbaf..1d1f1f2eb9e8c 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1331,6 +1331,7 @@ interface ArrayConstructor { (arrayLength?: number): any[]; (arrayLength: number): T[]; (...items: T[]): T[]; + isArray(arg: {} | null | undefined | ReadonlyArray): arg is ReadonlyArray; isArray(arg: any): arg is Array; readonly prototype: Array; } diff --git a/tests/baselines/reference/isArray.errors.txt b/tests/baselines/reference/isArray.errors.txt new file mode 100644 index 0000000000000..0442dba9b81d0 --- /dev/null +++ b/tests/baselines/reference/isArray.errors.txt @@ -0,0 +1,71 @@ +tests/cases/compiler/isArray.ts(5,11): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/isArray.ts(16,11): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/isArray.ts(17,24): error TS2339: Property 'push' does not exist on type 'ReadonlyArray'. +tests/cases/compiler/isArray.ts(27,11): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/isArray.ts(28,28): error TS2339: Property 'push' does not exist on type 'ReadonlyArray'. +tests/cases/compiler/isArray.ts(30,5): error TS2533: Object is possibly 'null' or 'undefined'. + + +==== tests/cases/compiler/isArray.ts (6 errors) ==== + var maybeArray = [] as Array | number; + + if (Array.isArray(maybeArray)) { + maybeArray.length; // OK + const str: string = maybeArray[0]; // Expect error + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + maybeArray.push(42); // OK + } else { + maybeArray.toFixed(2); // OK + } + + + var maybeReadonlyArray = [] as ReadonlyArray | number; + + if (Array.isArray(maybeReadonlyArray)) { + maybeReadonlyArray.length; // OK + const str: string = maybeReadonlyArray[0]; // Expect error + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + maybeReadonlyArray.push(42); // Expect error + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'ReadonlyArray'. + } else { + maybeReadonlyArray.toFixed(2); // OK + } + + + var readonlyArrayOrNullish: ReadonlyArray | undefined | null; + + if (Array.isArray(readonlyArrayOrNullish)) { + readonlyArrayOrNullish.length; // OK + const str: string = readonlyArrayOrNullish[0]; // Expect error + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + readonlyArrayOrNullish.push(42); // Expect error + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'ReadonlyArray'. + } else { + readonlyArrayOrNullish.X; // Expect error + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2533: Object is possibly 'null' or 'undefined'. + } + + + var someUnknown: unknown; + + if (Array.isArray(someUnknown)) { + someUnknown.length; // OK + const str: string = someUnknown[0]; // OK + someUnknown.push("anything"); // OK + } + + + var someAny: any; + + if (Array.isArray(someAny)) { + someAny.length; // OK + const str: string = someAny[0]; // OK + someAny.push("anything"); // OK + } + \ No newline at end of file diff --git a/tests/baselines/reference/isArray.js b/tests/baselines/reference/isArray.js index a90898fd65b26..0dcd7ebd854a5 100644 --- a/tests/baselines/reference/isArray.js +++ b/tests/baselines/reference/isArray.js @@ -1,19 +1,92 @@ //// [isArray.ts] -var maybeArray: number | number[]; - +var maybeArray = [] as Array | number; if (Array.isArray(maybeArray)) { maybeArray.length; // OK + const str: string = maybeArray[0]; // Expect error + maybeArray.push(42); // OK +} else { + maybeArray.toFixed(2); // OK +} + + +var maybeReadonlyArray = [] as ReadonlyArray | number; + +if (Array.isArray(maybeReadonlyArray)) { + maybeReadonlyArray.length; // OK + const str: string = maybeReadonlyArray[0]; // Expect error + maybeReadonlyArray.push(42); // Expect error +} else { + maybeReadonlyArray.toFixed(2); // OK +} + + +var readonlyArrayOrNullish: ReadonlyArray | undefined | null; + +if (Array.isArray(readonlyArrayOrNullish)) { + readonlyArrayOrNullish.length; // OK + const str: string = readonlyArrayOrNullish[0]; // Expect error + readonlyArrayOrNullish.push(42); // Expect error +} else { + readonlyArrayOrNullish.X; // Expect error +} + + +var someUnknown: unknown; + +if (Array.isArray(someUnknown)) { + someUnknown.length; // OK + const str: string = someUnknown[0]; // OK + someUnknown.push("anything"); // OK +} + + +var someAny: any; + +if (Array.isArray(someAny)) { + someAny.length; // OK + const str: string = someAny[0]; // OK + someAny.push("anything"); // OK } -else { - maybeArray.toFixed(); // OK -} + //// [isArray.js] -var maybeArray; +var maybeArray = []; if (Array.isArray(maybeArray)) { maybeArray.length; // OK + var str = maybeArray[0]; // Expect error + maybeArray.push(42); // OK } else { - maybeArray.toFixed(); // OK + maybeArray.toFixed(2); // OK +} +var maybeReadonlyArray = []; +if (Array.isArray(maybeReadonlyArray)) { + maybeReadonlyArray.length; // OK + var str = maybeReadonlyArray[0]; // Expect error + maybeReadonlyArray.push(42); // Expect error +} +else { + maybeReadonlyArray.toFixed(2); // OK +} +var readonlyArrayOrNullish; +if (Array.isArray(readonlyArrayOrNullish)) { + readonlyArrayOrNullish.length; // OK + var str = readonlyArrayOrNullish[0]; // Expect error + readonlyArrayOrNullish.push(42); // Expect error +} +else { + readonlyArrayOrNullish.X; // Expect error +} +var someUnknown; +if (Array.isArray(someUnknown)) { + someUnknown.length; // OK + var str = someUnknown[0]; // OK + someUnknown.push("anything"); // OK +} +var someAny; +if (Array.isArray(someAny)) { + someAny.length; // OK + var str = someAny[0]; // OK + someAny.push("anything"); // OK } diff --git a/tests/baselines/reference/isArray.symbols b/tests/baselines/reference/isArray.symbols index 411cb42918daa..702921b9766cf 100644 --- a/tests/baselines/reference/isArray.symbols +++ b/tests/baselines/reference/isArray.symbols @@ -1,22 +1,140 @@ === tests/cases/compiler/isArray.ts === -var maybeArray: number | number[]; +var maybeArray = [] as Array | number; >maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) - +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) if (Array.isArray(maybeArray)) { ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) maybeArray.length; // OK >maybeArray.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) >maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) >length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) -} -else { - maybeArray.toFixed(); // OK + + const str: string = maybeArray[0]; // Expect error +>str : Symbol(str, Decl(isArray.ts, 4, 9)) +>maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) + + maybeArray.push(42); // OK +>maybeArray.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + +} else { + maybeArray.toFixed(2); // OK >maybeArray.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) >maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) >toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) } + + +var maybeReadonlyArray = [] as ReadonlyArray | number; +>maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + +if (Array.isArray(maybeReadonlyArray)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) + + maybeReadonlyArray.length; // OK +>maybeReadonlyArray.length : Symbol(ReadonlyArray.length, Decl(lib.es5.d.ts, --, --)) +>maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) +>length : Symbol(ReadonlyArray.length, Decl(lib.es5.d.ts, --, --)) + + const str: string = maybeReadonlyArray[0]; // Expect error +>str : Symbol(str, Decl(isArray.ts, 15, 9)) +>maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) + + maybeReadonlyArray.push(42); // Expect error +>maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) + +} else { + maybeReadonlyArray.toFixed(2); // OK +>maybeReadonlyArray.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +} + + +var readonlyArrayOrNullish: ReadonlyArray | undefined | null; +>readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + +if (Array.isArray(readonlyArrayOrNullish)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) + + readonlyArrayOrNullish.length; // OK +>readonlyArrayOrNullish.length : Symbol(ReadonlyArray.length, Decl(lib.es5.d.ts, --, --)) +>readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) +>length : Symbol(ReadonlyArray.length, Decl(lib.es5.d.ts, --, --)) + + const str: string = readonlyArrayOrNullish[0]; // Expect error +>str : Symbol(str, Decl(isArray.ts, 26, 9)) +>readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) + + readonlyArrayOrNullish.push(42); // Expect error +>readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) + +} else { + readonlyArrayOrNullish.X; // Expect error +>readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) +} + + +var someUnknown: unknown; +>someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) + +if (Array.isArray(someUnknown)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) + + someUnknown.length; // OK +>someUnknown.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + const str: string = someUnknown[0]; // OK +>str : Symbol(str, Decl(isArray.ts, 37, 9)) +>someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) + + someUnknown.push("anything"); // OK +>someUnknown.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + + +var someAny: any; +>someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) + +if (Array.isArray(someAny)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) + + someAny.length; // OK +>someAny.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + + const str: string = someAny[0]; // OK +>str : Symbol(str, Decl(isArray.ts, 46, 9)) +>someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) + + someAny.push("anything"); // OK +>someAny.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + diff --git a/tests/baselines/reference/isArray.types b/tests/baselines/reference/isArray.types index bc452b12bef01..fc5bf31b770e1 100644 --- a/tests/baselines/reference/isArray.types +++ b/tests/baselines/reference/isArray.types @@ -1,24 +1,177 @@ === tests/cases/compiler/isArray.ts === -var maybeArray: number | number[]; +var maybeArray = [] as Array | number; >maybeArray : number | number[] - +>[] as Array | number : number | number[] +>[] : never[] if (Array.isArray(maybeArray)) { >Array.isArray(maybeArray) : boolean ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } >maybeArray : number | number[] maybeArray.length; // OK >maybeArray.length : number >maybeArray : number[] >length : number -} -else { - maybeArray.toFixed(); // OK ->maybeArray.toFixed() : string ->maybeArray.toFixed : (fractionDigits?: number) => string + + const str: string = maybeArray[0]; // Expect error +>str : string +>maybeArray[0] : number +>maybeArray : number[] +>0 : 0 + + maybeArray.push(42); // OK +>maybeArray.push(42) : number +>maybeArray.push : (...items: number[]) => number +>maybeArray : number[] +>push : (...items: number[]) => number +>42 : 42 + +} else { + maybeArray.toFixed(2); // OK +>maybeArray.toFixed(2) : string +>maybeArray.toFixed : (fractionDigits?: number | undefined) => string >maybeArray : number ->toFixed : (fractionDigits?: number) => string +>toFixed : (fractionDigits?: number | undefined) => string +>2 : 2 +} + + +var maybeReadonlyArray = [] as ReadonlyArray | number; +>maybeReadonlyArray : number | ReadonlyArray +>[] as ReadonlyArray | number : number | ReadonlyArray +>[] : never[] + +if (Array.isArray(maybeReadonlyArray)) { +>Array.isArray(maybeReadonlyArray) : boolean +>Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array : ArrayConstructor +>isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } +>maybeReadonlyArray : number | ReadonlyArray + + maybeReadonlyArray.length; // OK +>maybeReadonlyArray.length : number +>maybeReadonlyArray : ReadonlyArray +>length : number + + const str: string = maybeReadonlyArray[0]; // Expect error +>str : string +>maybeReadonlyArray[0] : number +>maybeReadonlyArray : ReadonlyArray +>0 : 0 + + maybeReadonlyArray.push(42); // Expect error +>maybeReadonlyArray.push(42) : any +>maybeReadonlyArray.push : any +>maybeReadonlyArray : ReadonlyArray +>push : any +>42 : 42 + +} else { + maybeReadonlyArray.toFixed(2); // OK +>maybeReadonlyArray.toFixed(2) : string +>maybeReadonlyArray.toFixed : (fractionDigits?: number | undefined) => string +>maybeReadonlyArray : number +>toFixed : (fractionDigits?: number | undefined) => string +>2 : 2 +} + + +var readonlyArrayOrNullish: ReadonlyArray | undefined | null; +>readonlyArrayOrNullish : ReadonlyArray | null | undefined +>null : null + +if (Array.isArray(readonlyArrayOrNullish)) { +>Array.isArray(readonlyArrayOrNullish) : boolean +>Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array : ArrayConstructor +>isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } +>readonlyArrayOrNullish : ReadonlyArray | null | undefined + + readonlyArrayOrNullish.length; // OK +>readonlyArrayOrNullish.length : number +>readonlyArrayOrNullish : ReadonlyArray +>length : number + + const str: string = readonlyArrayOrNullish[0]; // Expect error +>str : string +>readonlyArrayOrNullish[0] : number +>readonlyArrayOrNullish : ReadonlyArray +>0 : 0 + + readonlyArrayOrNullish.push(42); // Expect error +>readonlyArrayOrNullish.push(42) : any +>readonlyArrayOrNullish.push : any +>readonlyArrayOrNullish : ReadonlyArray +>push : any +>42 : 42 + +} else { + readonlyArrayOrNullish.X; // Expect error +>readonlyArrayOrNullish.X : any +>readonlyArrayOrNullish : null | undefined +>X : any } + + +var someUnknown: unknown; +>someUnknown : unknown + +if (Array.isArray(someUnknown)) { +>Array.isArray(someUnknown) : boolean +>Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array : ArrayConstructor +>isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } +>someUnknown : unknown + + someUnknown.length; // OK +>someUnknown.length : number +>someUnknown : any[] +>length : number + + const str: string = someUnknown[0]; // OK +>str : string +>someUnknown[0] : any +>someUnknown : any[] +>0 : 0 + + someUnknown.push("anything"); // OK +>someUnknown.push("anything") : number +>someUnknown.push : (...items: any[]) => number +>someUnknown : any[] +>push : (...items: any[]) => number +>"anything" : "anything" +} + + +var someAny: any; +>someAny : any + +if (Array.isArray(someAny)) { +>Array.isArray(someAny) : boolean +>Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array : ArrayConstructor +>isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } +>someAny : any + + someAny.length; // OK +>someAny.length : number +>someAny : any[] +>length : number + + const str: string = someAny[0]; // OK +>str : string +>someAny[0] : any +>someAny : any[] +>0 : 0 + + someAny.push("anything"); // OK +>someAny.push("anything") : number +>someAny.push : (...items: any[]) => number +>someAny : any[] +>push : (...items: any[]) => number +>"anything" : "anything" +} + diff --git a/tests/cases/compiler/isArray.ts b/tests/cases/compiler/isArray.ts index dbdd875e21ecc..ad862753af799 100644 --- a/tests/cases/compiler/isArray.ts +++ b/tests/cases/compiler/isArray.ts @@ -1,9 +1,51 @@ -var maybeArray: number | number[]; +// @strictNullChecks: true +var maybeArray = [] as Array | number; if (Array.isArray(maybeArray)) { maybeArray.length; // OK + const str: string = maybeArray[0]; // Expect error + maybeArray.push(42); // OK +} else { + maybeArray.toFixed(2); // OK +} + + +var maybeReadonlyArray = [] as ReadonlyArray | number; + +if (Array.isArray(maybeReadonlyArray)) { + maybeReadonlyArray.length; // OK + const str: string = maybeReadonlyArray[0]; // Expect error + maybeReadonlyArray.push(42); // Expect error +} else { + maybeReadonlyArray.toFixed(2); // OK +} + + +var readonlyArrayOrNullish: ReadonlyArray | undefined | null; + +if (Array.isArray(readonlyArrayOrNullish)) { + readonlyArrayOrNullish.length; // OK + const str: string = readonlyArrayOrNullish[0]; // Expect error + readonlyArrayOrNullish.push(42); // Expect error +} else { + readonlyArrayOrNullish.X; // Expect error +} + + +var someUnknown: unknown; + +if (Array.isArray(someUnknown)) { + someUnknown.length; // OK + const str: string = someUnknown[0]; // OK + someUnknown.push("anything"); // OK +} + + +var someAny: any; + +if (Array.isArray(someAny)) { + someAny.length; // OK + const str: string = someAny[0]; // OK + someAny.push("anything"); // OK } -else { - maybeArray.toFixed(); // OK -} \ No newline at end of file From f02bdcbc8bd537031cd296b5b7bf2e1e99d7a4a9 Mon Sep 17 00:00:00 2001 From: Ulrich Buchgraber Date: Sat, 8 Dec 2018 02:21:34 +0100 Subject: [PATCH 2/6] Accept remaining baselines --- .../destructuringParameterDeclaration4.errors.txt | 2 +- tests/baselines/reference/fixSignatureCaching.symbols | 4 ++-- tests/baselines/reference/fixSignatureCaching.types | 4 ++-- .../literalFreshnessPropagationOnNarrowing.symbols | 8 ++++---- .../literalFreshnessPropagationOnNarrowing.types | 8 ++++---- tests/baselines/reference/malformedTags.symbols | 4 ++-- tests/baselines/reference/malformedTags.types | 4 ++-- tests/baselines/reference/parserharness.symbols | 8 ++++---- tests/baselines/reference/parserharness.types | 8 ++++---- .../reference/partiallyDiscriminantedUnions.symbols | 4 ++-- .../reference/partiallyDiscriminantedUnions.types | 4 ++-- tests/baselines/reference/promisePermutations.errors.txt | 2 +- tests/baselines/reference/promisePermutations2.errors.txt | 2 +- tests/baselines/reference/promisePermutations3.errors.txt | 4 ++-- tests/baselines/reference/promiseTypeInference.errors.txt | 2 +- .../reference/spreadBooleanRespectsFreshness.symbols | 4 ++-- .../reference/spreadBooleanRespectsFreshness.types | 4 ++-- 17 files changed, 38 insertions(+), 38 deletions(-) diff --git a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt index e51ee68b60414..717df1f0af61c 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt @@ -41,7 +41,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts( a1(...array2); // Error parameter type is (number|string)[] ~~~~~~ !!! error TS2552: Cannot find name 'array2'. Did you mean 'Array'? -!!! related TS2728 /.ts/lib.es5.d.ts:1358:15: 'Array' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1359:15: 'Array' is declared here. a5([1, 2, "string", false, true]); // Error, parameter type is [any, any, [[any]]] ~~~~~~~~ !!! error TS2322: Type 'string' is not assignable to type '[[any]]'. diff --git a/tests/baselines/reference/fixSignatureCaching.symbols b/tests/baselines/reference/fixSignatureCaching.symbols index aecfdf18e592d..6c610e534dca4 100644 --- a/tests/baselines/reference/fixSignatureCaching.symbols +++ b/tests/baselines/reference/fixSignatureCaching.symbols @@ -796,9 +796,9 @@ define(function () { >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; }; ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >value : Symbol(value, Decl(fixSignatureCaching.ts, 297, 34)) >Object.prototype.toString.call : Symbol(Function.call, Decl(lib.es5.d.ts, --, --)) >Object.prototype.toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --)) diff --git a/tests/baselines/reference/fixSignatureCaching.types b/tests/baselines/reference/fixSignatureCaching.types index c278034e2cb75..0bf5a2cd48ac6 100644 --- a/tests/baselines/reference/fixSignatureCaching.types +++ b/tests/baselines/reference/fixSignatureCaching.types @@ -1109,9 +1109,9 @@ define(function () { >Array : ArrayConstructor Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; }; ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >function (value) { return Object.prototype.toString.call(value) === '[object Array]'; } : (value: any) => boolean >value : any >Object.prototype.toString.call(value) === '[object Array]' : boolean diff --git a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.symbols b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.symbols index 790def0be4318..7d783ed26771a 100644 --- a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.symbols +++ b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.symbols @@ -61,9 +61,9 @@ function f2() { let a4: ElementOrArray = Array.isArray(elOrA) ? elOrA : [elOrA]; >a4 : Symbol(a4, Decl(literalFreshnessPropagationOnNarrowing.ts, 21, 7)) >ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) @@ -74,9 +74,9 @@ function f2() { let a5: ElementOrArray = [...Array.isArray(elOrA) ? elOrA : [elOrA]]; >a5 : Symbol(a5, Decl(literalFreshnessPropagationOnNarrowing.ts, 26, 7)) >ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) diff --git a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.types b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.types index 8fb03bc413f30..3aa536278e452 100644 --- a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.types +++ b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.types @@ -66,9 +66,9 @@ function f2() { >a4 : string | false | (string | false)[] >Array.isArray(elOrA) ? elOrA : [elOrA] : (string | false)[] >Array.isArray(elOrA) : boolean ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >elOrA : string | false | (string | false)[] >elOrA : (string | false)[] >[elOrA] : (string | false)[] @@ -83,9 +83,9 @@ function f2() { >...Array.isArray(elOrA) ? elOrA : [elOrA] : string | false >Array.isArray(elOrA) ? elOrA : [elOrA] : (string | false)[] >Array.isArray(elOrA) : boolean ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >elOrA : string | false | (string | false)[] >elOrA : (string | false)[] >[elOrA] : (string | false)[] diff --git a/tests/baselines/reference/malformedTags.symbols b/tests/baselines/reference/malformedTags.symbols index bd0dc3d4a80f8..4d8b6db454e2e 100644 --- a/tests/baselines/reference/malformedTags.symbols +++ b/tests/baselines/reference/malformedTags.symbols @@ -6,7 +6,7 @@ */ var isArray = Array.isArray; >isArray : Symbol(isArray, Decl(myFile02.js, 5, 3)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) diff --git a/tests/baselines/reference/malformedTags.types b/tests/baselines/reference/malformedTags.types index c3af959586790..0d32935b40480 100644 --- a/tests/baselines/reference/malformedTags.types +++ b/tests/baselines/reference/malformedTags.types @@ -6,7 +6,7 @@ */ var isArray = Array.isArray; >isArray : Function ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } diff --git a/tests/baselines/reference/parserharness.symbols b/tests/baselines/reference/parserharness.symbols index 85fcd37d626ee..77542adf799be 100644 --- a/tests/baselines/reference/parserharness.symbols +++ b/tests/baselines/reference/parserharness.symbols @@ -2371,12 +2371,12 @@ module Harness { >arg : Symbol(arg, Decl(parserharness.ts, 806, 36)) if ((Array.isArray && Array.isArray(arg)) || arg instanceof Array) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(parserharness.ts, 806, 36)) >arg : Symbol(arg, Decl(parserharness.ts, 806, 36)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) diff --git a/tests/baselines/reference/parserharness.types b/tests/baselines/reference/parserharness.types index 1d29ff9430521..c7beb70b6e75f 100644 --- a/tests/baselines/reference/parserharness.types +++ b/tests/baselines/reference/parserharness.types @@ -3068,13 +3068,13 @@ module Harness { >(Array.isArray && Array.isArray(arg)) || arg instanceof Array : boolean >(Array.isArray && Array.isArray(arg)) : boolean >Array.isArray && Array.isArray(arg) : boolean ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array.isArray(arg) : boolean ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >arg : any >arg instanceof Array : boolean >arg : any diff --git a/tests/baselines/reference/partiallyDiscriminantedUnions.symbols b/tests/baselines/reference/partiallyDiscriminantedUnions.symbols index c8096894943d9..c30f45c053aa5 100644 --- a/tests/baselines/reference/partiallyDiscriminantedUnions.symbols +++ b/tests/baselines/reference/partiallyDiscriminantedUnions.symbols @@ -88,9 +88,9 @@ function isShape(s : Shapes): s is Shape { >Shape : Symbol(Shape, Decl(partiallyDiscriminantedUnions.ts, 30, 32)) return !Array.isArray(s); ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >s : Symbol(s, Decl(partiallyDiscriminantedUnions.ts, 35, 17)) } diff --git a/tests/baselines/reference/partiallyDiscriminantedUnions.types b/tests/baselines/reference/partiallyDiscriminantedUnions.types index f1d44249c0eb2..65fc5a31b78a6 100644 --- a/tests/baselines/reference/partiallyDiscriminantedUnions.types +++ b/tests/baselines/reference/partiallyDiscriminantedUnions.types @@ -77,9 +77,9 @@ function isShape(s : Shapes): s is Shape { return !Array.isArray(s); >!Array.isArray(s) : boolean >Array.isArray(s) : boolean ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >s : Shapes } diff --git a/tests/baselines/reference/promisePermutations.errors.txt b/tests/baselines/reference/promisePermutations.errors.txt index 7d1112dab175f..a76e96f296bbe 100644 --- a/tests/baselines/reference/promisePermutations.errors.txt +++ b/tests/baselines/reference/promisePermutations.errors.txt @@ -295,7 +295,7 @@ tests/cases/compiler/promisePermutations.ts(160,21): error TS2345: Argument of t ~~~~~~~~~ !!! error TS2345: Argument of type '(x: any) => IPromise' is not assignable to parameter of type '(error: any) => Promise'. !!! error TS2345: Property 'catch' is missing in type 'IPromise' but required in type 'Promise'. -!!! related TS2728 /.ts/lib.es5.d.ts:1403:5: 'catch' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1404:5: 'catch' is declared here. var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok var r11: IPromise; diff --git a/tests/baselines/reference/promisePermutations2.errors.txt b/tests/baselines/reference/promisePermutations2.errors.txt index 10abb661feb11..8ddb40543c086 100644 --- a/tests/baselines/reference/promisePermutations2.errors.txt +++ b/tests/baselines/reference/promisePermutations2.errors.txt @@ -294,7 +294,7 @@ tests/cases/compiler/promisePermutations2.ts(159,21): error TS2345: Argument of ~~~~~~~~~ !!! error TS2345: Argument of type '(x: any) => IPromise' is not assignable to parameter of type '(error: any) => Promise'. !!! error TS2345: Property 'catch' is missing in type 'IPromise' but required in type 'Promise'. -!!! related TS2728 /.ts/lib.es5.d.ts:1403:5: 'catch' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1404:5: 'catch' is declared here. var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok var r11: IPromise; diff --git a/tests/baselines/reference/promisePermutations3.errors.txt b/tests/baselines/reference/promisePermutations3.errors.txt index 733eae63c5f13..e62cd111fec70 100644 --- a/tests/baselines/reference/promisePermutations3.errors.txt +++ b/tests/baselines/reference/promisePermutations3.errors.txt @@ -303,7 +303,7 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of ~~~~~~~~~ !!! error TS2345: Argument of type '(x: any) => IPromise' is not assignable to parameter of type '(error: any) => Promise'. !!! error TS2345: Property 'catch' is missing in type 'IPromise' but required in type 'Promise'. -!!! related TS2728 /.ts/lib.es5.d.ts:1403:5: 'catch' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1404:5: 'catch' is declared here. var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok var r11: IPromise; @@ -340,5 +340,5 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of ~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '{ (x: T): IPromise; (x: T, y: T): Promise; }' is not assignable to parameter of type '(value: (x: any) => any) => Promise<{}>'. !!! error TS2345: Property 'catch' is missing in type 'IPromise' but required in type 'Promise<{}>'. -!!! related TS2728 /.ts/lib.es5.d.ts:1403:5: 'catch' is declared here. +!!! related TS2728 /.ts/lib.es5.d.ts:1404:5: 'catch' is declared here. var s12c = s12.then(testFunction12P, testFunction12, testFunction12); // ok \ No newline at end of file diff --git a/tests/baselines/reference/promiseTypeInference.errors.txt b/tests/baselines/reference/promiseTypeInference.errors.txt index 5edf8f5b0918e..f79b7cc0215af 100644 --- a/tests/baselines/reference/promiseTypeInference.errors.txt +++ b/tests/baselines/reference/promiseTypeInference.errors.txt @@ -26,5 +26,5 @@ tests/cases/compiler/promiseTypeInference.ts(10,39): error TS2322: Type 'IPromis !!! error TS2322: Types of parameters 'success' and 'onfulfilled' are incompatible. !!! error TS2322: Type 'TResult1 | PromiseLike' is not assignable to type 'IPromise'. !!! error TS2322: Type 'TResult1' is not assignable to type 'IPromise'. -!!! related TS6502 /.ts/lib.es5.d.ts:1396:57: The expected type comes from the return type of this signature. +!!! related TS6502 /.ts/lib.es5.d.ts:1397:57: The expected type comes from the return type of this signature. \ No newline at end of file diff --git a/tests/baselines/reference/spreadBooleanRespectsFreshness.symbols b/tests/baselines/reference/spreadBooleanRespectsFreshness.symbols index 90e9a7dace3d1..269f68db30aa7 100644 --- a/tests/baselines/reference/spreadBooleanRespectsFreshness.symbols +++ b/tests/baselines/reference/spreadBooleanRespectsFreshness.symbols @@ -21,9 +21,9 @@ declare let foo2: Foo; foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]]; >foo1 : Symbol(foo1, Decl(spreadBooleanRespectsFreshness.ts, 4, 11)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11)) >foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11)) >foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11)) diff --git a/tests/baselines/reference/spreadBooleanRespectsFreshness.types b/tests/baselines/reference/spreadBooleanRespectsFreshness.types index c607422b0629a..d27b140ac5ab8 100644 --- a/tests/baselines/reference/spreadBooleanRespectsFreshness.types +++ b/tests/baselines/reference/spreadBooleanRespectsFreshness.types @@ -22,9 +22,9 @@ foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]]; >...Array.isArray(foo2) ? foo2 : [foo2] : FooBase >Array.isArray(foo2) ? foo2 : [foo2] : FooBase[] >Array.isArray(foo2) : boolean ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } >foo2 : Foo >foo2 : FooBase[] >[foo2] : FooBase[] From 57fa898d8134c60aab3704ab870234a3653934eb Mon Sep 17 00:00:00 2001 From: Ulrich Buchgraber Date: Wed, 17 Jul 2019 03:42:34 +0200 Subject: [PATCH 3/6] Switch to alternative which uses conditional types instead of an overload for 'isArray' This has the advantage that it upcasts non-array inputs to Array instead of ReadonlyArray (=> no breaking change in this case). --- src/lib/es5.d.ts | 3 +- ...InternalTypesProduceUniqueTypeParams.types | 4 +- .../reference/fixSignatureCaching.symbols | 4 +- .../reference/fixSignatureCaching.types | 4 +- tests/baselines/reference/isArray.errors.txt | 149 +++-- tests/baselines/reference/isArray.js | 221 +++++--- tests/baselines/reference/isArray.symbols | 407 ++++++++++---- tests/baselines/reference/isArray.types | 522 +++++++++++++----- ...ralFreshnessPropagationOnNarrowing.symbols | 8 +- ...teralFreshnessPropagationOnNarrowing.types | 8 +- .../baselines/reference/malformedTags.symbols | 4 +- tests/baselines/reference/malformedTags.types | 4 +- .../baselines/reference/parserharness.symbols | 8 +- tests/baselines/reference/parserharness.types | 44 +- .../partiallyDiscriminantedUnions.symbols | 4 +- .../partiallyDiscriminantedUnions.types | 4 +- .../spreadBooleanRespectsFreshness.symbols | 4 +- .../spreadBooleanRespectsFreshness.types | 4 +- tests/cases/compiler/isArray.ts | 95 ++-- 19 files changed, 1072 insertions(+), 429 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 140cf7ea199c2..d39978f5c1a0b 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1341,8 +1341,7 @@ interface ArrayConstructor { (arrayLength?: number): any[]; (arrayLength: number): T[]; (...items: T[]): T[]; - isArray(arg: {} | null | undefined | ReadonlyArray): arg is ReadonlyArray; - isArray(arg: any): arg is Array; + isArray(arg: T): arg is T extends ReadonlyArray ? T : Array extends T ? (T & any[]) : never; readonly prototype: Array; } diff --git a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types index 68e2e12c65dbb..8fce630fecb93 100644 --- a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types +++ b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types @@ -67,9 +67,9 @@ export const updateIfChanged = (t: T) => { >assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } >Array.isArray(u) ? [] : {} : undefined[] | {} >Array.isArray(u) : boolean ->Array.isArray : (arg: any) => arg is any[] +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : (arg: any) => arg is any[] +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >u : U >[] : undefined[] >{} : {} diff --git a/tests/baselines/reference/fixSignatureCaching.symbols b/tests/baselines/reference/fixSignatureCaching.symbols index be56951d148d6..97efe41ce1205 100644 --- a/tests/baselines/reference/fixSignatureCaching.symbols +++ b/tests/baselines/reference/fixSignatureCaching.symbols @@ -796,9 +796,9 @@ define(function () { >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; }; ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >value : Symbol(value, Decl(fixSignatureCaching.ts, 297, 34)) >Object.prototype.toString.call : Symbol(Function.call, Decl(lib.es5.d.ts, --, --)) >Object.prototype.toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --)) diff --git a/tests/baselines/reference/fixSignatureCaching.types b/tests/baselines/reference/fixSignatureCaching.types index 54e52d2b263b7..914e651864670 100644 --- a/tests/baselines/reference/fixSignatureCaching.types +++ b/tests/baselines/reference/fixSignatureCaching.types @@ -1109,9 +1109,9 @@ define(function () { >Array : ArrayConstructor Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; }; ->Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >function (value) { return Object.prototype.toString.call(value) === '[object Array]'; } : (value: any) => boolean >value : any >Object.prototype.toString.call(value) === '[object Array]' : boolean diff --git a/tests/baselines/reference/isArray.errors.txt b/tests/baselines/reference/isArray.errors.txt index 0442dba9b81d0..e76ddff84633a 100644 --- a/tests/baselines/reference/isArray.errors.txt +++ b/tests/baselines/reference/isArray.errors.txt @@ -1,71 +1,120 @@ -tests/cases/compiler/isArray.ts(5,11): error TS2322: Type 'number' is not assignable to type 'string'. -tests/cases/compiler/isArray.ts(16,11): error TS2322: Type 'number' is not assignable to type 'string'. -tests/cases/compiler/isArray.ts(17,24): error TS2339: Property 'push' does not exist on type 'ReadonlyArray'. -tests/cases/compiler/isArray.ts(27,11): error TS2322: Type 'number' is not assignable to type 'string'. -tests/cases/compiler/isArray.ts(28,28): error TS2339: Property 'push' does not exist on type 'ReadonlyArray'. -tests/cases/compiler/isArray.ts(30,5): error TS2533: Object is possibly 'null' or 'undefined'. +tests/cases/compiler/isArray.ts(21,33): error TS2339: Property 'push' does not exist on type 'readonly string[]'. +tests/cases/compiler/isArray.ts(22,33): error TS2339: Property 'push' does not exist on type 'readonly string[]'. +tests/cases/compiler/isArray.ts(28,38): error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. +tests/cases/compiler/isArray.ts(36,33): error TS2339: Property 'push' does not exist on type 'readonly string[] | number[]'. + Property 'push' does not exist on type 'readonly string[]'. +tests/cases/compiler/isArray.ts(40,33): error TS2339: Property 'push' does not exist on type 'readonly string[] | number[]'. + Property 'push' does not exist on type 'readonly string[]'. +tests/cases/compiler/isArray.ts(44,38): error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. +tests/cases/compiler/isArray.ts(50,33): error TS2339: Property 'push' does not exist on type 'MyReadOnlyArray'. +tests/cases/compiler/isArray.ts(51,41): error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. +tests/cases/compiler/isArray.ts(61,33): error TS2339: Property 'push' does not exist on type 'readonly T[]'. +tests/cases/compiler/isArray.ts(70,33): error TS2339: Property 'push' does not exist on type 'readonly [T]'. -==== tests/cases/compiler/isArray.ts (6 errors) ==== - var maybeArray = [] as Array | number; +==== tests/cases/compiler/isArray.ts (10 errors) ==== + interface MyArray extends Array { manifest: any; } + interface MyReadOnlyArray extends ReadonlyArray { manifest: any; } - if (Array.isArray(maybeArray)) { - maybeArray.length; // OK - const str: string = maybeArray[0]; // Expect error - ~~~ -!!! error TS2322: Type 'number' is not assignable to type 'string'. - maybeArray.push(42); // OK - } else { - maybeArray.toFixed(2); // OK + function fn1(arg: string | string[]) { + if (Array.isArray(arg)) arg.push(""); // Should OK } + function fn2(arg: unknown) { + if (Array.isArray(arg)) arg.push(""); // Should OK + } + + function fn3(arg: object) { + if (Array.isArray(arg)) arg.push(""); // Should OK + } + + function fn4(arg: {}) { + if (Array.isArray(arg)) arg.push(""); // Should OK + } + + function fn5(arg: string | ReadonlyArray) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'readonly string[]'. + if (Array.isArray(arg)) arg.push(""); // Should FAIL + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'readonly string[]'. + if (Array.isArray(arg)) arg.indexOf(""); // Should OK + if (!Array.isArray(arg)) arg.toUpperCase(); // Should OK + } + + function fn6(arg: string | string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + ~~ +!!! error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. + } - var maybeReadonlyArray = [] as ReadonlyArray | number; + function fn7(arg: boolean | number[] | string[]) { + if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK + } - if (Array.isArray(maybeReadonlyArray)) { - maybeReadonlyArray.length; // OK - const str: string = maybeReadonlyArray[0]; // Expect error - ~~~ -!!! error TS2322: Type 'number' is not assignable to type 'string'. - maybeReadonlyArray.push(42); // Expect error - ~~~~ -!!! error TS2339: Property 'push' does not exist on type 'ReadonlyArray'. - } else { - maybeReadonlyArray.toFixed(2); // OK + function fn8(arg: string | number[] | readonly string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'readonly string[] | number[]'. +!!! error TS2339: Property 'push' does not exist on type 'readonly string[]'. } + function fn9(arg: string | number[] | readonly string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'readonly string[] | number[]'. +!!! error TS2339: Property 'push' does not exist on type 'readonly string[]'. + } - var readonlyArrayOrNullish: ReadonlyArray | undefined | null; + function fn10(arg: string | MyArray) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + ~~ +!!! error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. + if (Array.isArray(arg)) arg.push(""); // Should OK + if (Array.isArray(arg)) arg.manifest; // Should OK + } - if (Array.isArray(readonlyArrayOrNullish)) { - readonlyArrayOrNullish.length; // OK - const str: string = readonlyArrayOrNullish[0]; // Expect error - ~~~ -!!! error TS2322: Type 'number' is not assignable to type 'string'. - readonlyArrayOrNullish.push(42); // Expect error - ~~~~ -!!! error TS2339: Property 'push' does not exist on type 'ReadonlyArray'. - } else { - readonlyArrayOrNullish.X; // Expect error - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2533: Object is possibly 'null' or 'undefined'. + function fn11(arg: string | MyReadOnlyArray) { + if (Array.isArray(arg)) arg.push(""); // Should FAIL + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'MyReadOnlyArray'. + if (Array.isArray(arg)) arg.indexOf(10); // Should FAIL + ~~ +!!! error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. + if (Array.isArray(arg)) arg.indexOf(""); // Should OK + if (Array.isArray(arg)) arg.manifest; // Should OK } + function fn12(arg: T | T[]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK + } - var someUnknown: unknown; + function fn13(arg: T | ReadonlyArray) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'readonly T[]'. + if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK + } - if (Array.isArray(someUnknown)) { - someUnknown.length; // OK - const str: string = someUnknown[0]; // OK - someUnknown.push("anything"); // OK + function fn14(arg: T | [T]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK } + function fn15(arg: T | readonly [T]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + ~~~~ +!!! error TS2339: Property 'push' does not exist on type 'readonly [T]'. + if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK + } - var someAny: any; + function fn16(arg: T) { + if (Array.isArray(arg)) arg.push("10"); // Should OK + } - if (Array.isArray(someAny)) { - someAny.length; // OK - const str: string = someAny[0]; // OK - someAny.push("anything"); // OK + function fn17() { + const s: Array = []; + const arrs = s.filter(Array.isArray); + arrs.push(["one"]); } \ No newline at end of file diff --git a/tests/baselines/reference/isArray.js b/tests/baselines/reference/isArray.js index 0dcd7ebd854a5..7495e6b37010f 100644 --- a/tests/baselines/reference/isArray.js +++ b/tests/baselines/reference/isArray.js @@ -1,92 +1,175 @@ //// [isArray.ts] -var maybeArray = [] as Array | number; +interface MyArray extends Array { manifest: any; } +interface MyReadOnlyArray extends ReadonlyArray { manifest: any; } -if (Array.isArray(maybeArray)) { - maybeArray.length; // OK - const str: string = maybeArray[0]; // Expect error - maybeArray.push(42); // OK -} else { - maybeArray.toFixed(2); // OK +function fn1(arg: string | string[]) { + if (Array.isArray(arg)) arg.push(""); // Should OK } +function fn2(arg: unknown) { + if (Array.isArray(arg)) arg.push(""); // Should OK +} + +function fn3(arg: object) { + if (Array.isArray(arg)) arg.push(""); // Should OK +} + +function fn4(arg: {}) { + if (Array.isArray(arg)) arg.push(""); // Should OK +} + +function fn5(arg: string | ReadonlyArray) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + if (Array.isArray(arg)) arg.push(""); // Should FAIL + if (Array.isArray(arg)) arg.indexOf(""); // Should OK + if (!Array.isArray(arg)) arg.toUpperCase(); // Should OK +} + +function fn6(arg: string | string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL +} -var maybeReadonlyArray = [] as ReadonlyArray | number; +function fn7(arg: boolean | number[] | string[]) { + if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK +} -if (Array.isArray(maybeReadonlyArray)) { - maybeReadonlyArray.length; // OK - const str: string = maybeReadonlyArray[0]; // Expect error - maybeReadonlyArray.push(42); // Expect error -} else { - maybeReadonlyArray.toFixed(2); // OK +function fn8(arg: string | number[] | readonly string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL } +function fn9(arg: string | number[] | readonly string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL +} -var readonlyArrayOrNullish: ReadonlyArray | undefined | null; +function fn10(arg: string | MyArray) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + if (Array.isArray(arg)) arg.push(""); // Should OK + if (Array.isArray(arg)) arg.manifest; // Should OK +} -if (Array.isArray(readonlyArrayOrNullish)) { - readonlyArrayOrNullish.length; // OK - const str: string = readonlyArrayOrNullish[0]; // Expect error - readonlyArrayOrNullish.push(42); // Expect error -} else { - readonlyArrayOrNullish.X; // Expect error +function fn11(arg: string | MyReadOnlyArray) { + if (Array.isArray(arg)) arg.push(""); // Should FAIL + if (Array.isArray(arg)) arg.indexOf(10); // Should FAIL + if (Array.isArray(arg)) arg.indexOf(""); // Should OK + if (Array.isArray(arg)) arg.manifest; // Should OK } +function fn12(arg: T | T[]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +} -var someUnknown: unknown; +function fn13(arg: T | ReadonlyArray) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK +} -if (Array.isArray(someUnknown)) { - someUnknown.length; // OK - const str: string = someUnknown[0]; // OK - someUnknown.push("anything"); // OK +function fn14(arg: T | [T]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK } +function fn15(arg: T | readonly [T]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK +} -var someAny: any; +function fn16(arg: T) { + if (Array.isArray(arg)) arg.push("10"); // Should OK +} -if (Array.isArray(someAny)) { - someAny.length; // OK - const str: string = someAny[0]; // OK - someAny.push("anything"); // OK +function fn17() { + const s: Array = []; + const arrs = s.filter(Array.isArray); + arrs.push(["one"]); } //// [isArray.js] -var maybeArray = []; -if (Array.isArray(maybeArray)) { - maybeArray.length; // OK - var str = maybeArray[0]; // Expect error - maybeArray.push(42); // OK -} -else { - maybeArray.toFixed(2); // OK -} -var maybeReadonlyArray = []; -if (Array.isArray(maybeReadonlyArray)) { - maybeReadonlyArray.length; // OK - var str = maybeReadonlyArray[0]; // Expect error - maybeReadonlyArray.push(42); // Expect error -} -else { - maybeReadonlyArray.toFixed(2); // OK -} -var readonlyArrayOrNullish; -if (Array.isArray(readonlyArrayOrNullish)) { - readonlyArrayOrNullish.length; // OK - var str = readonlyArrayOrNullish[0]; // Expect error - readonlyArrayOrNullish.push(42); // Expect error -} -else { - readonlyArrayOrNullish.X; // Expect error -} -var someUnknown; -if (Array.isArray(someUnknown)) { - someUnknown.length; // OK - var str = someUnknown[0]; // OK - someUnknown.push("anything"); // OK -} -var someAny; -if (Array.isArray(someAny)) { - someAny.length; // OK - var str = someAny[0]; // OK - someAny.push("anything"); // OK +function fn1(arg) { + if (Array.isArray(arg)) + arg.push(""); // Should OK +} +function fn2(arg) { + if (Array.isArray(arg)) + arg.push(""); // Should OK +} +function fn3(arg) { + if (Array.isArray(arg)) + arg.push(""); // Should OK +} +function fn4(arg) { + if (Array.isArray(arg)) + arg.push(""); // Should OK +} +function fn5(arg) { + if (Array.isArray(arg)) + arg.push(10); // Should FAIL + if (Array.isArray(arg)) + arg.push(""); // Should FAIL + if (Array.isArray(arg)) + arg.indexOf(""); // Should OK + if (!Array.isArray(arg)) + arg.toUpperCase(); // Should OK +} +function fn6(arg) { + if (Array.isArray(arg)) + arg.push(10); // Should FAIL +} +function fn7(arg) { + if (Array.isArray(arg)) + arg.push(null); // Should OK +} +function fn8(arg) { + if (Array.isArray(arg)) + arg.push(10); // Should FAIL +} +function fn9(arg) { + if (Array.isArray(arg)) + arg.push(10); // Should FAIL +} +function fn10(arg) { + if (Array.isArray(arg)) + arg.push(10); // Should FAIL + if (Array.isArray(arg)) + arg.push(""); // Should OK + if (Array.isArray(arg)) + arg.manifest; // Should OK +} +function fn11(arg) { + if (Array.isArray(arg)) + arg.push(""); // Should FAIL + if (Array.isArray(arg)) + arg.indexOf(10); // Should FAIL + if (Array.isArray(arg)) + arg.indexOf(""); // Should OK + if (Array.isArray(arg)) + arg.manifest; // Should OK +} +function fn12(arg) { + if (Array.isArray(arg)) + arg.push(null); // Should OK +} +function fn13(arg) { + if (Array.isArray(arg)) + arg.push(null); // Should fail + if (Array.isArray(arg)) + arg.indexOf(null); // OK +} +function fn14(arg) { + if (Array.isArray(arg)) + arg.push(null); // Should OK +} +function fn15(arg) { + if (Array.isArray(arg)) + arg.push(null); // Should fail + if (Array.isArray(arg)) + arg.indexOf(null); // Should OK +} +function fn16(arg) { + if (Array.isArray(arg)) + arg.push("10"); // Should OK +} +function fn17() { + var s = []; + var arrs = s.filter(Array.isArray); + arrs.push(["one"]); } diff --git a/tests/baselines/reference/isArray.symbols b/tests/baselines/reference/isArray.symbols index 702921b9766cf..1015c0e197998 100644 --- a/tests/baselines/reference/isArray.symbols +++ b/tests/baselines/reference/isArray.symbols @@ -1,140 +1,361 @@ === tests/cases/compiler/isArray.ts === -var maybeArray = [] as Array | number; ->maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) +interface MyArray extends Array { manifest: any; } +>MyArray : Symbol(MyArray, Decl(isArray.ts, 0, 0)) +>T : Symbol(T, Decl(isArray.ts, 0, 18)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(isArray.ts, 0, 18)) +>manifest : Symbol(MyArray.manifest, Decl(isArray.ts, 0, 39)) -if (Array.isArray(maybeArray)) { ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) +interface MyReadOnlyArray extends ReadonlyArray { manifest: any; } +>MyReadOnlyArray : Symbol(MyReadOnlyArray, Decl(isArray.ts, 0, 56)) +>T : Symbol(T, Decl(isArray.ts, 1, 26)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(isArray.ts, 1, 26)) +>manifest : Symbol(MyReadOnlyArray.manifest, Decl(isArray.ts, 1, 55)) - maybeArray.length; // OK ->maybeArray.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) ->maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) ->length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +function fn1(arg: string | string[]) { +>fn1 : Symbol(fn1, Decl(isArray.ts, 1, 72)) +>arg : Symbol(arg, Decl(isArray.ts, 3, 13)) + + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 3, 13)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 3, 13)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} - const str: string = maybeArray[0]; // Expect error ->str : Symbol(str, Decl(isArray.ts, 4, 9)) ->maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) +function fn2(arg: unknown) { +>fn2 : Symbol(fn2, Decl(isArray.ts, 5, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 7, 13)) - maybeArray.push(42); // OK ->maybeArray.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 7, 13)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 7, 13)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} -} else { - maybeArray.toFixed(2); // OK ->maybeArray.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->maybeArray : Symbol(maybeArray, Decl(isArray.ts, 0, 3)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +function fn3(arg: object) { +>fn3 : Symbol(fn3, Decl(isArray.ts, 9, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 11, 13)) + + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 11, 13)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 11, 13)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } +function fn4(arg: {}) { +>fn4 : Symbol(fn4, Decl(isArray.ts, 13, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 15, 13)) + + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 15, 13)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 15, 13)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} -var maybeReadonlyArray = [] as ReadonlyArray | number; ->maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) +function fn5(arg: string | ReadonlyArray) { +>fn5 : Symbol(fn5, Decl(isArray.ts, 17, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) >ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) -if (Array.isArray(maybeReadonlyArray)) { ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) - maybeReadonlyArray.length; // OK ->maybeReadonlyArray.length : Symbol(ReadonlyArray.length, Decl(lib.es5.d.ts, --, --)) ->maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) ->length : Symbol(ReadonlyArray.length, Decl(lib.es5.d.ts, --, --)) + if (Array.isArray(arg)) arg.push(""); // Should FAIL +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) - const str: string = maybeReadonlyArray[0]; // Expect error ->str : Symbol(str, Decl(isArray.ts, 15, 9)) ->maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) + if (Array.isArray(arg)) arg.indexOf(""); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) +>arg.indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) +>indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) + + if (!Array.isArray(arg)) arg.toUpperCase(); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) +>arg.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 19, 13)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +} - maybeReadonlyArray.push(42); // Expect error ->maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) +function fn6(arg: string | string[]) { +>fn6 : Symbol(fn6, Decl(isArray.ts, 24, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 26, 13)) -} else { - maybeReadonlyArray.toFixed(2); // OK ->maybeReadonlyArray.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->maybeReadonlyArray : Symbol(maybeReadonlyArray, Decl(isArray.ts, 11, 3)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 26, 13)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 26, 13)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } +function fn7(arg: boolean | number[] | string[]) { +>fn7 : Symbol(fn7, Decl(isArray.ts, 28, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 30, 13)) -var readonlyArrayOrNullish: ReadonlyArray | undefined | null; ->readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) ->ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 30, 13)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 30, 13)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +} -if (Array.isArray(readonlyArrayOrNullish)) { ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +function fn8(arg: string | number[] | readonly string[]) { +>fn8 : Symbol(fn8, Decl(isArray.ts, 32, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 34, 13)) + + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 34, 13)) +>arg : Symbol(arg, Decl(isArray.ts, 34, 13)) +} - readonlyArrayOrNullish.length; // OK ->readonlyArrayOrNullish.length : Symbol(ReadonlyArray.length, Decl(lib.es5.d.ts, --, --)) ->readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) ->length : Symbol(ReadonlyArray.length, Decl(lib.es5.d.ts, --, --)) +function fn9(arg: string | number[] | readonly string[]) { +>fn9 : Symbol(fn9, Decl(isArray.ts, 36, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 38, 13)) - const str: string = readonlyArrayOrNullish[0]; // Expect error ->str : Symbol(str, Decl(isArray.ts, 26, 9)) ->readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 38, 13)) +>arg : Symbol(arg, Decl(isArray.ts, 38, 13)) +} - readonlyArrayOrNullish.push(42); // Expect error ->readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) +function fn10(arg: string | MyArray) { +>fn10 : Symbol(fn10, Decl(isArray.ts, 40, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 42, 14)) +>MyArray : Symbol(MyArray, Decl(isArray.ts, 0, 0)) + + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 42, 14)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 42, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) -} else { - readonlyArrayOrNullish.X; // Expect error ->readonlyArrayOrNullish : Symbol(readonlyArrayOrNullish, Decl(isArray.ts, 22, 3)) + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 42, 14)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 42, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + if (Array.isArray(arg)) arg.manifest; // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 42, 14)) +>arg.manifest : Symbol(MyArray.manifest, Decl(isArray.ts, 0, 39)) +>arg : Symbol(arg, Decl(isArray.ts, 42, 14)) +>manifest : Symbol(MyArray.manifest, Decl(isArray.ts, 0, 39)) } +function fn11(arg: string | MyReadOnlyArray) { +>fn11 : Symbol(fn11, Decl(isArray.ts, 46, 1)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) +>MyReadOnlyArray : Symbol(MyReadOnlyArray, Decl(isArray.ts, 0, 56)) + + if (Array.isArray(arg)) arg.push(""); // Should FAIL +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) + + if (Array.isArray(arg)) arg.indexOf(10); // Should FAIL +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) +>arg.indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) +>indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) + + if (Array.isArray(arg)) arg.indexOf(""); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) +>arg.indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) +>indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) + + if (Array.isArray(arg)) arg.manifest; // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) +>arg.manifest : Symbol(MyReadOnlyArray.manifest, Decl(isArray.ts, 1, 55)) +>arg : Symbol(arg, Decl(isArray.ts, 48, 14)) +>manifest : Symbol(MyReadOnlyArray.manifest, Decl(isArray.ts, 1, 55)) +} + +function fn12(arg: T | T[]) { +>fn12 : Symbol(fn12, Decl(isArray.ts, 53, 1)) +>T : Symbol(T, Decl(isArray.ts, 55, 14)) +>arg : Symbol(arg, Decl(isArray.ts, 55, 17)) +>T : Symbol(T, Decl(isArray.ts, 55, 14)) +>T : Symbol(T, Decl(isArray.ts, 55, 14)) + + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 55, 17)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 55, 17)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(isArray.ts, 55, 14)) +} -var someUnknown: unknown; ->someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) +function fn13(arg: T | ReadonlyArray) { +>fn13 : Symbol(fn13, Decl(isArray.ts, 57, 1)) +>T : Symbol(T, Decl(isArray.ts, 59, 14)) +>arg : Symbol(arg, Decl(isArray.ts, 59, 17)) +>T : Symbol(T, Decl(isArray.ts, 59, 14)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(isArray.ts, 59, 14)) -if (Array.isArray(someUnknown)) { ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 59, 17)) +>arg : Symbol(arg, Decl(isArray.ts, 59, 17)) +>T : Symbol(T, Decl(isArray.ts, 59, 14)) - someUnknown.length; // OK ->someUnknown.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) ->someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) ->length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 59, 17)) +>arg.indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 59, 17)) +>indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(isArray.ts, 59, 14)) +} - const str: string = someUnknown[0]; // OK ->str : Symbol(str, Decl(isArray.ts, 37, 9)) ->someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) +function fn14(arg: T | [T]) { +>fn14 : Symbol(fn14, Decl(isArray.ts, 62, 1)) +>T : Symbol(T, Decl(isArray.ts, 64, 14)) +>arg : Symbol(arg, Decl(isArray.ts, 64, 17)) +>T : Symbol(T, Decl(isArray.ts, 64, 14)) +>T : Symbol(T, Decl(isArray.ts, 64, 14)) - someUnknown.push("anything"); // OK ->someUnknown.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->someUnknown : Symbol(someUnknown, Decl(isArray.ts, 33, 3)) + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 64, 17)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 64, 17)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(isArray.ts, 64, 14)) } +function fn15(arg: T | readonly [T]) { +>fn15 : Symbol(fn15, Decl(isArray.ts, 66, 1)) +>T : Symbol(T, Decl(isArray.ts, 68, 14)) +>arg : Symbol(arg, Decl(isArray.ts, 68, 17)) +>T : Symbol(T, Decl(isArray.ts, 68, 14)) +>T : Symbol(T, Decl(isArray.ts, 68, 14)) -var someAny: any; ->someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 68, 17)) +>arg : Symbol(arg, Decl(isArray.ts, 68, 17)) +>T : Symbol(T, Decl(isArray.ts, 68, 14)) -if (Array.isArray(someAny)) { ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 68, 17)) +>arg.indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 68, 17)) +>indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(isArray.ts, 68, 14)) +} - someAny.length; // OK ->someAny.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) ->someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) ->length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +function fn16(arg: T) { +>fn16 : Symbol(fn16, Decl(isArray.ts, 71, 1)) +>T : Symbol(T, Decl(isArray.ts, 73, 14)) +>arg : Symbol(arg, Decl(isArray.ts, 73, 43)) +>T : Symbol(T, Decl(isArray.ts, 73, 14)) - const str: string = someAny[0]; // OK ->str : Symbol(str, Decl(isArray.ts, 46, 9)) ->someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) + if (Array.isArray(arg)) arg.push("10"); // Should OK +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 73, 43)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 73, 43)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function fn17() { +>fn17 : Symbol(fn17, Decl(isArray.ts, 75, 1)) + + const s: Array = []; +>s : Symbol(s, Decl(isArray.ts, 78, 9)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + const arrs = s.filter(Array.isArray); +>arrs : Symbol(arrs, Decl(isArray.ts, 79, 9)) +>s.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>s : Symbol(s, Decl(isArray.ts, 78, 9)) +>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) - someAny.push("anything"); // OK ->someAny.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->someAny : Symbol(someAny, Decl(isArray.ts, 42, 3)) + arrs.push(["one"]); +>arrs.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arrs : Symbol(arrs, Decl(isArray.ts, 79, 9)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } diff --git a/tests/baselines/reference/isArray.types b/tests/baselines/reference/isArray.types index fc5bf31b770e1..38f81f8823ed0 100644 --- a/tests/baselines/reference/isArray.types +++ b/tests/baselines/reference/isArray.types @@ -1,177 +1,435 @@ === tests/cases/compiler/isArray.ts === -var maybeArray = [] as Array | number; ->maybeArray : number | number[] ->[] as Array | number : number | number[] ->[] : never[] +interface MyArray extends Array { manifest: any; } +>manifest : any -if (Array.isArray(maybeArray)) { ->Array.isArray(maybeArray) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } ->Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } ->maybeArray : number | number[] +interface MyReadOnlyArray extends ReadonlyArray { manifest: any; } +>manifest : any - maybeArray.length; // OK ->maybeArray.length : number ->maybeArray : number[] ->length : number +function fn1(arg: string | string[]) { +>fn1 : (arg: string | string[]) => void +>arg : string | string[] - const str: string = maybeArray[0]; // Expect error ->str : string ->maybeArray[0] : number ->maybeArray : number[] ->0 : 0 + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | string[] +>arg.push("") : number +>arg.push : (...items: string[]) => number +>arg : string[] +>push : (...items: string[]) => number +>"" : "" +} - maybeArray.push(42); // OK ->maybeArray.push(42) : number ->maybeArray.push : (...items: number[]) => number ->maybeArray : number[] ->push : (...items: number[]) => number ->42 : 42 +function fn2(arg: unknown) { +>fn2 : (arg: unknown) => void +>arg : unknown -} else { - maybeArray.toFixed(2); // OK ->maybeArray.toFixed(2) : string ->maybeArray.toFixed : (fractionDigits?: number | undefined) => string ->maybeArray : number ->toFixed : (fractionDigits?: number | undefined) => string ->2 : 2 + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : unknown +>arg.push("") : number +>arg.push : (...items: any[]) => number +>arg : any[] +>push : (...items: any[]) => number +>"" : "" } +function fn3(arg: object) { +>fn3 : (arg: object) => void +>arg : object -var maybeReadonlyArray = [] as ReadonlyArray | number; ->maybeReadonlyArray : number | ReadonlyArray ->[] as ReadonlyArray | number : number | ReadonlyArray ->[] : never[] + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : object +>arg.push("") : number +>arg.push : (...items: any[]) => number +>arg : object & any[] +>push : (...items: any[]) => number +>"" : "" +} + +function fn4(arg: {}) { +>fn4 : (arg: {}) => void +>arg : {} -if (Array.isArray(maybeReadonlyArray)) { ->Array.isArray(maybeReadonlyArray) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } ->maybeReadonlyArray : number | ReadonlyArray +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : {} +>arg.push("") : number +>arg.push : (...items: any[]) => number +>arg : any[] +>push : (...items: any[]) => number +>"" : "" +} - maybeReadonlyArray.length; // OK ->maybeReadonlyArray.length : number ->maybeReadonlyArray : ReadonlyArray ->length : number +function fn5(arg: string | ReadonlyArray) { +>fn5 : (arg: string | readonly string[]) => void +>arg : string | readonly string[] - const str: string = maybeReadonlyArray[0]; // Expect error ->str : string ->maybeReadonlyArray[0] : number ->maybeReadonlyArray : ReadonlyArray ->0 : 0 + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | readonly string[] +>arg.push(10) : any +>arg.push : any +>arg : readonly string[] +>push : any +>10 : 10 - maybeReadonlyArray.push(42); // Expect error ->maybeReadonlyArray.push(42) : any ->maybeReadonlyArray.push : any ->maybeReadonlyArray : ReadonlyArray + if (Array.isArray(arg)) arg.push(""); // Should FAIL +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | readonly string[] +>arg.push("") : any +>arg.push : any +>arg : readonly string[] >push : any ->42 : 42 +>"" : "" -} else { - maybeReadonlyArray.toFixed(2); // OK ->maybeReadonlyArray.toFixed(2) : string ->maybeReadonlyArray.toFixed : (fractionDigits?: number | undefined) => string ->maybeReadonlyArray : number ->toFixed : (fractionDigits?: number | undefined) => string ->2 : 2 + if (Array.isArray(arg)) arg.indexOf(""); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | readonly string[] +>arg.indexOf("") : number +>arg.indexOf : (searchElement: string, fromIndex?: number | undefined) => number +>arg : readonly string[] +>indexOf : (searchElement: string, fromIndex?: number | undefined) => number +>"" : "" + + if (!Array.isArray(arg)) arg.toUpperCase(); // Should OK +>!Array.isArray(arg) : boolean +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | readonly string[] +>arg.toUpperCase() : string +>arg.toUpperCase : () => string +>arg : string +>toUpperCase : () => string +} + +function fn6(arg: string | string[]) { +>fn6 : (arg: string | string[]) => void +>arg : string | string[] + + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | string[] +>arg.push(10) : number +>arg.push : (...items: string[]) => number +>arg : string[] +>push : (...items: string[]) => number +>10 : 10 } +function fn7(arg: boolean | number[] | string[]) { +>fn7 : (arg: boolean | string[] | number[]) => void +>arg : boolean | string[] | number[] -var readonlyArrayOrNullish: ReadonlyArray | undefined | null; ->readonlyArrayOrNullish : ReadonlyArray | null | undefined + if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : boolean | string[] | number[] +>arg.push(null as any as string & number) : number +>arg.push : ((...items: string[]) => number) | ((...items: number[]) => number) +>arg : string[] | number[] +>push : ((...items: string[]) => number) | ((...items: number[]) => number) +>null as any as string & number : never +>null as any : any >null : null +} + +function fn8(arg: string | number[] | readonly string[]) { +>fn8 : (arg: string | readonly string[] | number[]) => void +>arg : string | readonly string[] | number[] -if (Array.isArray(readonlyArrayOrNullish)) { ->Array.isArray(readonlyArrayOrNullish) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } ->readonlyArrayOrNullish : ReadonlyArray | null | undefined +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | readonly string[] | number[] +>arg.push(10) : any +>arg.push : any +>arg : readonly string[] | number[] +>push : any +>10 : 10 +} - readonlyArrayOrNullish.length; // OK ->readonlyArrayOrNullish.length : number ->readonlyArrayOrNullish : ReadonlyArray ->length : number +function fn9(arg: string | number[] | readonly string[]) { +>fn9 : (arg: string | readonly string[] | number[]) => void +>arg : string | readonly string[] | number[] + + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | readonly string[] | number[] +>arg.push(10) : any +>arg.push : any +>arg : readonly string[] | number[] +>push : any +>10 : 10 +} - const str: string = readonlyArrayOrNullish[0]; // Expect error ->str : string ->readonlyArrayOrNullish[0] : number ->readonlyArrayOrNullish : ReadonlyArray ->0 : 0 +function fn10(arg: string | MyArray) { +>fn10 : (arg: string | MyArray) => void +>arg : string | MyArray - readonlyArrayOrNullish.push(42); // Expect error ->readonlyArrayOrNullish.push(42) : any ->readonlyArrayOrNullish.push : any ->readonlyArrayOrNullish : ReadonlyArray + if (Array.isArray(arg)) arg.push(10); // Should FAIL +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | MyArray +>arg.push(10) : number +>arg.push : (...items: string[]) => number +>arg : MyArray +>push : (...items: string[]) => number +>10 : 10 + + if (Array.isArray(arg)) arg.push(""); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | MyArray +>arg.push("") : number +>arg.push : (...items: string[]) => number +>arg : MyArray +>push : (...items: string[]) => number +>"" : "" + + if (Array.isArray(arg)) arg.manifest; // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | MyArray +>arg.manifest : any +>arg : MyArray +>manifest : any +} + +function fn11(arg: string | MyReadOnlyArray) { +>fn11 : (arg: string | MyReadOnlyArray) => void +>arg : string | MyReadOnlyArray + + if (Array.isArray(arg)) arg.push(""); // Should FAIL +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | MyReadOnlyArray +>arg.push("") : any +>arg.push : any +>arg : MyReadOnlyArray >push : any ->42 : 42 +>"" : "" -} else { - readonlyArrayOrNullish.X; // Expect error ->readonlyArrayOrNullish.X : any ->readonlyArrayOrNullish : null | undefined ->X : any + if (Array.isArray(arg)) arg.indexOf(10); // Should FAIL +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | MyReadOnlyArray +>arg.indexOf(10) : number +>arg.indexOf : (searchElement: string, fromIndex?: number | undefined) => number +>arg : MyReadOnlyArray +>indexOf : (searchElement: string, fromIndex?: number | undefined) => number +>10 : 10 + + if (Array.isArray(arg)) arg.indexOf(""); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | MyReadOnlyArray +>arg.indexOf("") : number +>arg.indexOf : (searchElement: string, fromIndex?: number | undefined) => number +>arg : MyReadOnlyArray +>indexOf : (searchElement: string, fromIndex?: number | undefined) => number +>"" : "" + + if (Array.isArray(arg)) arg.manifest; // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : string | MyReadOnlyArray +>arg.manifest : any +>arg : MyReadOnlyArray +>manifest : any } +function fn12(arg: T | T[]) { +>fn12 : (arg: T | T[]) => void +>arg : T | T[] -var someUnknown: unknown; ->someUnknown : unknown + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : T | T[] +>arg.push(null as any as T) : number +>arg.push : (...items: T[]) => number +>arg : T[] +>push : (...items: T[]) => number +>null as any as T : T +>null as any : any +>null : null +} + +function fn13(arg: T | ReadonlyArray) { +>fn13 : (arg: T | readonly T[]) => void +>arg : T | readonly T[] -if (Array.isArray(someUnknown)) { ->Array.isArray(someUnknown) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } ->someUnknown : unknown +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : T | readonly T[] +>arg.push(null as any as T) : any +>arg.push : any +>arg : readonly T[] +>push : any +>null as any as T : T +>null as any : any +>null : null - someUnknown.length; // OK ->someUnknown.length : number ->someUnknown : any[] ->length : number + if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : T | readonly T[] +>arg.indexOf(null as any as T) : number +>arg.indexOf : (searchElement: T, fromIndex?: number | undefined) => number +>arg : readonly T[] +>indexOf : (searchElement: T, fromIndex?: number | undefined) => number +>null as any as T : T +>null as any : any +>null : null +} - const str: string = someUnknown[0]; // OK ->str : string ->someUnknown[0] : any ->someUnknown : any[] ->0 : 0 +function fn14(arg: T | [T]) { +>fn14 : (arg: T | [T]) => void +>arg : T | [T] - someUnknown.push("anything"); // OK ->someUnknown.push("anything") : number ->someUnknown.push : (...items: any[]) => number ->someUnknown : any[] ->push : (...items: any[]) => number ->"anything" : "anything" + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : T | [T] +>arg.push(null as any as T) : number +>arg.push : (...items: T[]) => number +>arg : [T] +>push : (...items: T[]) => number +>null as any as T : T +>null as any : any +>null : null } +function fn15(arg: T | readonly [T]) { +>fn15 : (arg: T | readonly [T]) => void +>arg : T | readonly [T] + + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : T | readonly [T] +>arg.push(null as any as T) : any +>arg.push : any +>arg : readonly [T] +>push : any +>null as any as T : T +>null as any : any +>null : null + + if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : T | readonly [T] +>arg.indexOf(null as any as T) : number +>arg.indexOf : (searchElement: T, fromIndex?: number | undefined) => number +>arg : readonly [T] +>indexOf : (searchElement: T, fromIndex?: number | undefined) => number +>null as any as T : T +>null as any : any +>null : null +} -var someAny: any; ->someAny : any +function fn16(arg: T) { +>fn16 : (arg: T) => void +>arg : T -if (Array.isArray(someAny)) { ->Array.isArray(someAny) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } + if (Array.isArray(arg)) arg.push("10"); // Should OK +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray | null | undefined): arg is ReadonlyArray; (arg: any): arg is any[]; } ->someAny : any +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : T +>arg.push("10") : number +>arg.push : (...items: string[]) => number +>arg : T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>push : (...items: string[]) => number +>"10" : "10" +} - someAny.length; // OK ->someAny.length : number ->someAny : any[] ->length : number +function fn17() { +>fn17 : () => void - const str: string = someAny[0]; // OK ->str : string ->someAny[0] : any ->someAny : any[] ->0 : 0 + const s: Array = []; +>s : (string | string[])[] +>[] : never[] - someAny.push("anything"); // OK ->someAny.push("anything") : number ->someAny.push : (...items: any[]) => number ->someAny : any[] ->push : (...items: any[]) => number ->"anything" : "anything" + const arrs = s.filter(Array.isArray); +>arrs : string[][] +>s.filter(Array.isArray) : string[][] +>s.filter : { (callbackfn: (value: string | string[], index: number, array: (string | string[])[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: string | string[], index: number, array: (string | string[])[]) => unknown, thisArg?: any): (string | string[])[]; } +>s : (string | string[])[] +>filter : { (callbackfn: (value: string | string[], index: number, array: (string | string[])[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: string | string[], index: number, array: (string | string[])[]) => unknown, thisArg?: any): (string | string[])[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never + + arrs.push(["one"]); +>arrs.push(["one"]) : number +>arrs.push : (...items: string[][]) => number +>arrs : string[][] +>push : (...items: string[][]) => number +>["one"] : string[] +>"one" : "one" } diff --git a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.symbols b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.symbols index 7d783ed26771a..790def0be4318 100644 --- a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.symbols +++ b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.symbols @@ -61,9 +61,9 @@ function f2() { let a4: ElementOrArray = Array.isArray(elOrA) ? elOrA : [elOrA]; >a4 : Symbol(a4, Decl(literalFreshnessPropagationOnNarrowing.ts, 21, 7)) >ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) @@ -74,9 +74,9 @@ function f2() { let a5: ElementOrArray = [...Array.isArray(elOrA) ? elOrA : [elOrA]]; >a5 : Symbol(a5, Decl(literalFreshnessPropagationOnNarrowing.ts, 26, 7)) >ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) >elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7)) diff --git a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.types b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.types index 3aa536278e452..5d6f68578070d 100644 --- a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.types +++ b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.types @@ -66,9 +66,9 @@ function f2() { >a4 : string | false | (string | false)[] >Array.isArray(elOrA) ? elOrA : [elOrA] : (string | false)[] >Array.isArray(elOrA) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >elOrA : string | false | (string | false)[] >elOrA : (string | false)[] >[elOrA] : (string | false)[] @@ -83,9 +83,9 @@ function f2() { >...Array.isArray(elOrA) ? elOrA : [elOrA] : string | false >Array.isArray(elOrA) ? elOrA : [elOrA] : (string | false)[] >Array.isArray(elOrA) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >elOrA : string | false | (string | false)[] >elOrA : (string | false)[] >[elOrA] : (string | false)[] diff --git a/tests/baselines/reference/malformedTags.symbols b/tests/baselines/reference/malformedTags.symbols index 4d8b6db454e2e..bd0dc3d4a80f8 100644 --- a/tests/baselines/reference/malformedTags.symbols +++ b/tests/baselines/reference/malformedTags.symbols @@ -6,7 +6,7 @@ */ var isArray = Array.isArray; >isArray : Symbol(isArray, Decl(myFile02.js, 5, 3)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) diff --git a/tests/baselines/reference/malformedTags.types b/tests/baselines/reference/malformedTags.types index 0d32935b40480..1d3e2582bafa1 100644 --- a/tests/baselines/reference/malformedTags.types +++ b/tests/baselines/reference/malformedTags.types @@ -6,7 +6,7 @@ */ var isArray = Array.isArray; >isArray : Function ->Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never diff --git a/tests/baselines/reference/parserharness.symbols b/tests/baselines/reference/parserharness.symbols index 77542adf799be..85fcd37d626ee 100644 --- a/tests/baselines/reference/parserharness.symbols +++ b/tests/baselines/reference/parserharness.symbols @@ -2371,12 +2371,12 @@ module Harness { >arg : Symbol(arg, Decl(parserharness.ts, 806, 36)) if ((Array.isArray && Array.isArray(arg)) || arg instanceof Array) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(parserharness.ts, 806, 36)) >arg : Symbol(arg, Decl(parserharness.ts, 806, 36)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) diff --git a/tests/baselines/reference/parserharness.types b/tests/baselines/reference/parserharness.types index 2a75af301a51e..55e4c1cbf1e8e 100644 --- a/tests/baselines/reference/parserharness.types +++ b/tests/baselines/reference/parserharness.types @@ -3061,27 +3061,27 @@ module Harness { >identifier : any public normalizeToArray(arg: any) { ->normalizeToArray : (arg: any) => any[] +>normalizeToArray : (arg: any) => any >arg : any if ((Array.isArray && Array.isArray(arg)) || arg instanceof Array) >(Array.isArray && Array.isArray(arg)) || arg instanceof Array : boolean >(Array.isArray && Array.isArray(arg)) : boolean >Array.isArray && Array.isArray(arg) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array.isArray(arg) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >arg : any >arg instanceof Array : boolean >arg : any >Array : ArrayConstructor return arg; ->arg : any[] +>arg : any return [arg]; >[arg] : any[] @@ -3240,12 +3240,12 @@ module Harness { >others : any others = this.normalizeToArray(others); ->others = this.normalizeToArray(others) : any[] +>others = this.normalizeToArray(others) : any >others : any ->this.normalizeToArray(others) : any[] ->this.normalizeToArray : (arg: any) => any[] +>this.normalizeToArray(others) : any +>this.normalizeToArray : (arg: any) => any >this : this ->normalizeToArray : (arg: any) => any[] +>normalizeToArray : (arg: any) => any >others : any for (var i = 0; i < others.length; i++) { @@ -3294,12 +3294,12 @@ module Harness { >others : any others = this.normalizeToArray(others); ->others = this.normalizeToArray(others) : any[] +>others = this.normalizeToArray(others) : any >others : any ->this.normalizeToArray(others) : any[] ->this.normalizeToArray : (arg: any) => any[] +>this.normalizeToArray(others) : any +>this.normalizeToArray : (arg: any) => any >this : this ->normalizeToArray : (arg: any) => any[] +>normalizeToArray : (arg: any) => any >others : any for (var i = 0; i < others.length; i++) { @@ -3449,12 +3449,12 @@ module Harness { >others : any others = this.normalizeToArray(others); ->others = this.normalizeToArray(others) : any[] +>others = this.normalizeToArray(others) : any >others : any ->this.normalizeToArray(others) : any[] ->this.normalizeToArray : (arg: any) => any[] +>this.normalizeToArray(others) : any +>this.normalizeToArray : (arg: any) => any >this : this ->normalizeToArray : (arg: any) => any[] +>normalizeToArray : (arg: any) => any >others : any for (var i = 0; i < others.length; i++) { @@ -3505,12 +3505,12 @@ module Harness { >others : any others = this.normalizeToArray(others); ->others = this.normalizeToArray(others) : any[] +>others = this.normalizeToArray(others) : any >others : any ->this.normalizeToArray(others) : any[] ->this.normalizeToArray : (arg: any) => any[] +>this.normalizeToArray(others) : any +>this.normalizeToArray : (arg: any) => any >this : this ->normalizeToArray : (arg: any) => any[] +>normalizeToArray : (arg: any) => any >others : any for (var i = 0; i < others.length; i++) { diff --git a/tests/baselines/reference/partiallyDiscriminantedUnions.symbols b/tests/baselines/reference/partiallyDiscriminantedUnions.symbols index c30f45c053aa5..c8096894943d9 100644 --- a/tests/baselines/reference/partiallyDiscriminantedUnions.symbols +++ b/tests/baselines/reference/partiallyDiscriminantedUnions.symbols @@ -88,9 +88,9 @@ function isShape(s : Shapes): s is Shape { >Shape : Symbol(Shape, Decl(partiallyDiscriminantedUnions.ts, 30, 32)) return !Array.isArray(s); ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >s : Symbol(s, Decl(partiallyDiscriminantedUnions.ts, 35, 17)) } diff --git a/tests/baselines/reference/partiallyDiscriminantedUnions.types b/tests/baselines/reference/partiallyDiscriminantedUnions.types index 65fc5a31b78a6..0530f42889ade 100644 --- a/tests/baselines/reference/partiallyDiscriminantedUnions.types +++ b/tests/baselines/reference/partiallyDiscriminantedUnions.types @@ -77,9 +77,9 @@ function isShape(s : Shapes): s is Shape { return !Array.isArray(s); >!Array.isArray(s) : boolean >Array.isArray(s) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >s : Shapes } diff --git a/tests/baselines/reference/spreadBooleanRespectsFreshness.symbols b/tests/baselines/reference/spreadBooleanRespectsFreshness.symbols index 269f68db30aa7..90e9a7dace3d1 100644 --- a/tests/baselines/reference/spreadBooleanRespectsFreshness.symbols +++ b/tests/baselines/reference/spreadBooleanRespectsFreshness.symbols @@ -21,9 +21,9 @@ declare let foo2: Foo; foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]]; >foo1 : Symbol(foo1, Decl(spreadBooleanRespectsFreshness.ts, 4, 11)) ->Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11)) >foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11)) >foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11)) diff --git a/tests/baselines/reference/spreadBooleanRespectsFreshness.types b/tests/baselines/reference/spreadBooleanRespectsFreshness.types index d27b140ac5ab8..f3392084a6cab 100644 --- a/tests/baselines/reference/spreadBooleanRespectsFreshness.types +++ b/tests/baselines/reference/spreadBooleanRespectsFreshness.types @@ -22,9 +22,9 @@ foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]]; >...Array.isArray(foo2) ? foo2 : [foo2] : FooBase >Array.isArray(foo2) ? foo2 : [foo2] : FooBase[] >Array.isArray(foo2) : boolean ->Array.isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor ->isArray : { (arg: {} | ReadonlyArray): arg is ReadonlyArray; (arg: any): arg is any[]; } +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >foo2 : Foo >foo2 : FooBase[] >[foo2] : FooBase[] diff --git a/tests/cases/compiler/isArray.ts b/tests/cases/compiler/isArray.ts index ad862753af799..efc954acb0601 100644 --- a/tests/cases/compiler/isArray.ts +++ b/tests/cases/compiler/isArray.ts @@ -1,51 +1,84 @@ // @strictNullChecks: true -var maybeArray = [] as Array | number; +interface MyArray extends Array { manifest: any; } +interface MyReadOnlyArray extends ReadonlyArray { manifest: any; } -if (Array.isArray(maybeArray)) { - maybeArray.length; // OK - const str: string = maybeArray[0]; // Expect error - maybeArray.push(42); // OK -} else { - maybeArray.toFixed(2); // OK +function fn1(arg: string | string[]) { + if (Array.isArray(arg)) arg.push(""); // Should OK } +function fn2(arg: unknown) { + if (Array.isArray(arg)) arg.push(""); // Should OK +} + +function fn3(arg: object) { + if (Array.isArray(arg)) arg.push(""); // Should OK +} + +function fn4(arg: {}) { + if (Array.isArray(arg)) arg.push(""); // Should OK +} + +function fn5(arg: string | ReadonlyArray) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + if (Array.isArray(arg)) arg.push(""); // Should FAIL + if (Array.isArray(arg)) arg.indexOf(""); // Should OK + if (!Array.isArray(arg)) arg.toUpperCase(); // Should OK +} + +function fn6(arg: string | string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL +} -var maybeReadonlyArray = [] as ReadonlyArray | number; +function fn7(arg: boolean | number[] | string[]) { + if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK +} -if (Array.isArray(maybeReadonlyArray)) { - maybeReadonlyArray.length; // OK - const str: string = maybeReadonlyArray[0]; // Expect error - maybeReadonlyArray.push(42); // Expect error -} else { - maybeReadonlyArray.toFixed(2); // OK +function fn8(arg: string | number[] | readonly string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL } +function fn9(arg: string | number[] | readonly string[]) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL +} -var readonlyArrayOrNullish: ReadonlyArray | undefined | null; +function fn10(arg: string | MyArray) { + if (Array.isArray(arg)) arg.push(10); // Should FAIL + if (Array.isArray(arg)) arg.push(""); // Should OK + if (Array.isArray(arg)) arg.manifest; // Should OK +} -if (Array.isArray(readonlyArrayOrNullish)) { - readonlyArrayOrNullish.length; // OK - const str: string = readonlyArrayOrNullish[0]; // Expect error - readonlyArrayOrNullish.push(42); // Expect error -} else { - readonlyArrayOrNullish.X; // Expect error +function fn11(arg: string | MyReadOnlyArray) { + if (Array.isArray(arg)) arg.push(""); // Should FAIL + if (Array.isArray(arg)) arg.indexOf(10); // Should FAIL + if (Array.isArray(arg)) arg.indexOf(""); // Should OK + if (Array.isArray(arg)) arg.manifest; // Should OK } +function fn12(arg: T | T[]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +} -var someUnknown: unknown; +function fn13(arg: T | ReadonlyArray) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK +} -if (Array.isArray(someUnknown)) { - someUnknown.length; // OK - const str: string = someUnknown[0]; // OK - someUnknown.push("anything"); // OK +function fn14(arg: T | [T]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should OK } +function fn15(arg: T | readonly [T]) { + if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK +} -var someAny: any; +function fn16(arg: T) { + if (Array.isArray(arg)) arg.push("10"); // Should OK +} -if (Array.isArray(someAny)) { - someAny.length; // OK - const str: string = someAny[0]; // OK - someAny.push("anything"); // OK +function fn17() { + const s: Array = []; + const arrs = s.filter(Array.isArray); + arrs.push(["one"]); } From 93e902dfcdbea1d61e7093f6e95169ed1a2b954b Mon Sep 17 00:00:00 2001 From: Ulrich Buchgraber Date: Wed, 17 Jul 2019 04:15:34 +0200 Subject: [PATCH 4/6] Use parameters instead of casting of test types --- tests/baselines/reference/isArray.errors.txt | 24 +++---- tests/baselines/reference/isArray.js | 44 +++++++------ tests/baselines/reference/isArray.symbols | 38 ++++++----- tests/baselines/reference/isArray.types | 68 +++++++++----------- tests/cases/compiler/isArray.ts | 20 +++--- 5 files changed, 99 insertions(+), 95 deletions(-) diff --git a/tests/baselines/reference/isArray.errors.txt b/tests/baselines/reference/isArray.errors.txt index e76ddff84633a..8bf12aa3563c6 100644 --- a/tests/baselines/reference/isArray.errors.txt +++ b/tests/baselines/reference/isArray.errors.txt @@ -10,9 +10,11 @@ tests/cases/compiler/isArray.ts(50,33): error TS2339: Property 'push' does not e tests/cases/compiler/isArray.ts(51,41): error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. tests/cases/compiler/isArray.ts(61,33): error TS2339: Property 'push' does not exist on type 'readonly T[]'. tests/cases/compiler/isArray.ts(70,33): error TS2339: Property 'push' does not exist on type 'readonly [T]'. +tests/cases/compiler/isArray.ts(76,38): error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. +tests/cases/compiler/isArray.ts(83,15): error TS2345: Argument of type '"str"' is not assignable to parameter of type 'string[]'. -==== tests/cases/compiler/isArray.ts (10 errors) ==== +==== tests/cases/compiler/isArray.ts (12 errors) ==== interface MyArray extends Array { manifest: any; } interface MyReadOnlyArray extends ReadonlyArray { manifest: any; } @@ -49,8 +51,8 @@ tests/cases/compiler/isArray.ts(70,33): error TS2339: Property 'push' does not e !!! error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. } - function fn7(arg: boolean | number[] | string[]) { - if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK + function fn7(arg: boolean | number[] | string[], stringAndNumber: string & number) { + if (Array.isArray(arg)) arg.push(stringAndNumber); // Should OK } function fn8(arg: string | number[] | readonly string[]) { @@ -86,26 +88,26 @@ tests/cases/compiler/isArray.ts(70,33): error TS2339: Property 'push' does not e if (Array.isArray(arg)) arg.manifest; // Should OK } - function fn12(arg: T | T[]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK + function fn12(arg: T | T[], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should OK } - function fn13(arg: T | ReadonlyArray) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + function fn13(arg: T | ReadonlyArray, t: T) { + if (Array.isArray(arg)) arg.push(t); // Should fail ~~~~ !!! error TS2339: Property 'push' does not exist on type 'readonly T[]'. - if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK + if (Array.isArray(arg)) arg.indexOf(t); // OK } function fn14(arg: T | [T]) { if (Array.isArray(arg)) arg.push(null as any as T); // Should OK } - function fn15(arg: T | readonly [T]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + function fn15(arg: T | readonly [T], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should fail ~~~~ !!! error TS2339: Property 'push' does not exist on type 'readonly [T]'. - if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK + if (Array.isArray(arg)) arg.indexOf(t); // Should OK } function fn16(arg: T) { diff --git a/tests/baselines/reference/isArray.js b/tests/baselines/reference/isArray.js index 7495e6b37010f..7fb61313f91d9 100644 --- a/tests/baselines/reference/isArray.js +++ b/tests/baselines/reference/isArray.js @@ -29,8 +29,8 @@ function fn6(arg: string | string[]) { if (Array.isArray(arg)) arg.push(10); // Should FAIL } -function fn7(arg: boolean | number[] | string[]) { - if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK +function fn7(arg: boolean | number[] | string[], stringAndNumber: string & number) { + if (Array.isArray(arg)) arg.push(stringAndNumber); // Should OK } function fn8(arg: string | number[] | readonly string[]) { @@ -54,32 +54,34 @@ function fn11(arg: string | MyReadOnlyArray) { if (Array.isArray(arg)) arg.manifest; // Should OK } -function fn12(arg: T | T[]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +function fn12(arg: T | T[], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should OK } -function fn13(arg: T | ReadonlyArray) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail - if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK +function fn13(arg: T | ReadonlyArray, t: T) { + if (Array.isArray(arg)) arg.push(t); // Should fail + if (Array.isArray(arg)) arg.indexOf(t); // OK } function fn14(arg: T | [T]) { if (Array.isArray(arg)) arg.push(null as any as T); // Should OK } -function fn15(arg: T | readonly [T]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail - if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK +function fn15(arg: T | readonly [T], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should fail + if (Array.isArray(arg)) arg.indexOf(t); // Should OK } function fn16(arg: T) { if (Array.isArray(arg)) arg.push("10"); // Should OK + if (Array.isArray(arg)) arg.push(10); // Should fail } function fn17() { const s: Array = []; const arrs = s.filter(Array.isArray); - arrs.push(["one"]); + arrs.push(["one"]); // Should OK + arrs.push("str"); // Should fail } @@ -114,9 +116,9 @@ function fn6(arg) { if (Array.isArray(arg)) arg.push(10); // Should FAIL } -function fn7(arg) { +function fn7(arg, stringAndNumber) { if (Array.isArray(arg)) - arg.push(null); // Should OK + arg.push(stringAndNumber); // Should OK } function fn8(arg) { if (Array.isArray(arg)) @@ -144,25 +146,25 @@ function fn11(arg) { if (Array.isArray(arg)) arg.manifest; // Should OK } -function fn12(arg) { +function fn12(arg, t) { if (Array.isArray(arg)) - arg.push(null); // Should OK + arg.push(t); // Should OK } -function fn13(arg) { +function fn13(arg, t) { if (Array.isArray(arg)) - arg.push(null); // Should fail + arg.push(t); // Should fail if (Array.isArray(arg)) - arg.indexOf(null); // OK + arg.indexOf(t); // OK } function fn14(arg) { if (Array.isArray(arg)) arg.push(null); // Should OK } -function fn15(arg) { +function fn15(arg, t) { if (Array.isArray(arg)) - arg.push(null); // Should fail + arg.push(t); // Should fail if (Array.isArray(arg)) - arg.indexOf(null); // Should OK + arg.indexOf(t); // Should OK } function fn16(arg) { if (Array.isArray(arg)) diff --git a/tests/baselines/reference/isArray.symbols b/tests/baselines/reference/isArray.symbols index 1015c0e197998..3c7507759b417 100644 --- a/tests/baselines/reference/isArray.symbols +++ b/tests/baselines/reference/isArray.symbols @@ -121,11 +121,12 @@ function fn6(arg: string | string[]) { >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } -function fn7(arg: boolean | number[] | string[]) { +function fn7(arg: boolean | number[] | string[], stringAndNumber: string & number) { >fn7 : Symbol(fn7, Decl(isArray.ts, 28, 1)) >arg : Symbol(arg, Decl(isArray.ts, 30, 13)) +>stringAndNumber : Symbol(stringAndNumber, Decl(isArray.ts, 30, 48)) - if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK + if (Array.isArray(arg)) arg.push(stringAndNumber); // Should OK >Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) @@ -133,6 +134,7 @@ function fn7(arg: boolean | number[] | string[]) { >arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(isArray.ts, 30, 13)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>stringAndNumber : Symbol(stringAndNumber, Decl(isArray.ts, 30, 48)) } function fn8(arg: string | number[] | readonly string[]) { @@ -232,14 +234,16 @@ function fn11(arg: string | MyReadOnlyArray) { >manifest : Symbol(MyReadOnlyArray.manifest, Decl(isArray.ts, 1, 55)) } -function fn12(arg: T | T[]) { +function fn12(arg: T | T[], t: T) { >fn12 : Symbol(fn12, Decl(isArray.ts, 53, 1)) >T : Symbol(T, Decl(isArray.ts, 55, 14)) >arg : Symbol(arg, Decl(isArray.ts, 55, 17)) >T : Symbol(T, Decl(isArray.ts, 55, 14)) +>T : Symbol(T, Decl(isArray.ts, 55, 14)) +>t : Symbol(t, Decl(isArray.ts, 55, 30)) >T : Symbol(T, Decl(isArray.ts, 55, 14)) - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK + if (Array.isArray(arg)) arg.push(t); // Should OK >Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) @@ -247,26 +251,28 @@ function fn12(arg: T | T[]) { >arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(isArray.ts, 55, 17)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(isArray.ts, 55, 14)) +>t : Symbol(t, Decl(isArray.ts, 55, 30)) } -function fn13(arg: T | ReadonlyArray) { +function fn13(arg: T | ReadonlyArray, t: T) { >fn13 : Symbol(fn13, Decl(isArray.ts, 57, 1)) >T : Symbol(T, Decl(isArray.ts, 59, 14)) >arg : Symbol(arg, Decl(isArray.ts, 59, 17)) >T : Symbol(T, Decl(isArray.ts, 59, 14)) >ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(isArray.ts, 59, 14)) +>t : Symbol(t, Decl(isArray.ts, 59, 43)) >T : Symbol(T, Decl(isArray.ts, 59, 14)) - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + if (Array.isArray(arg)) arg.push(t); // Should fail >Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(isArray.ts, 59, 17)) >arg : Symbol(arg, Decl(isArray.ts, 59, 17)) ->T : Symbol(T, Decl(isArray.ts, 59, 14)) +>t : Symbol(t, Decl(isArray.ts, 59, 43)) - if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK + if (Array.isArray(arg)) arg.indexOf(t); // OK >Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) @@ -274,7 +280,7 @@ function fn13(arg: T | ReadonlyArray) { >arg.indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(isArray.ts, 59, 17)) >indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(isArray.ts, 59, 14)) +>t : Symbol(t, Decl(isArray.ts, 59, 43)) } function fn14(arg: T | [T]) { @@ -295,22 +301,24 @@ function fn14(arg: T | [T]) { >T : Symbol(T, Decl(isArray.ts, 64, 14)) } -function fn15(arg: T | readonly [T]) { +function fn15(arg: T | readonly [T], t: T) { >fn15 : Symbol(fn15, Decl(isArray.ts, 66, 1)) >T : Symbol(T, Decl(isArray.ts, 68, 14)) >arg : Symbol(arg, Decl(isArray.ts, 68, 17)) >T : Symbol(T, Decl(isArray.ts, 68, 14)) +>T : Symbol(T, Decl(isArray.ts, 68, 14)) +>t : Symbol(t, Decl(isArray.ts, 68, 39)) >T : Symbol(T, Decl(isArray.ts, 68, 14)) - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + if (Array.isArray(arg)) arg.push(t); // Should fail >Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(isArray.ts, 68, 17)) >arg : Symbol(arg, Decl(isArray.ts, 68, 17)) ->T : Symbol(T, Decl(isArray.ts, 68, 14)) +>t : Symbol(t, Decl(isArray.ts, 68, 39)) - if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK + if (Array.isArray(arg)) arg.indexOf(t); // Should OK >Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) @@ -318,7 +326,7 @@ function fn15(arg: T | readonly [T]) { >arg.indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(isArray.ts, 68, 17)) >indexOf : Symbol(ReadonlyArray.indexOf, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(isArray.ts, 68, 14)) +>t : Symbol(t, Decl(isArray.ts, 68, 39)) } function fn16(arg: T) { diff --git a/tests/baselines/reference/isArray.types b/tests/baselines/reference/isArray.types index 38f81f8823ed0..2dbaec499de43 100644 --- a/tests/baselines/reference/isArray.types +++ b/tests/baselines/reference/isArray.types @@ -143,23 +143,22 @@ function fn6(arg: string | string[]) { >10 : 10 } -function fn7(arg: boolean | number[] | string[]) { ->fn7 : (arg: boolean | string[] | number[]) => void +function fn7(arg: boolean | number[] | string[], stringAndNumber: string & number) { +>fn7 : (arg: boolean | string[] | number[], stringAndNumber: never) => void >arg : boolean | string[] | number[] +>stringAndNumber : never - if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK + if (Array.isArray(arg)) arg.push(stringAndNumber); // Should OK >Array.isArray(arg) : boolean >Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor >isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >arg : boolean | string[] | number[] ->arg.push(null as any as string & number) : number +>arg.push(stringAndNumber) : number >arg.push : ((...items: string[]) => number) | ((...items: number[]) => number) >arg : string[] | number[] >push : ((...items: string[]) => number) | ((...items: number[]) => number) ->null as any as string & number : never ->null as any : any ->null : null +>stringAndNumber : never } function fn8(arg: string | number[] | readonly string[]) { @@ -286,56 +285,52 @@ function fn11(arg: string | MyReadOnlyArray) { >manifest : any } -function fn12(arg: T | T[]) { ->fn12 : (arg: T | T[]) => void +function fn12(arg: T | T[], t: T) { +>fn12 : (arg: T | T[], t: T) => void >arg : T | T[] +>t : T - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK + if (Array.isArray(arg)) arg.push(t); // Should OK >Array.isArray(arg) : boolean >Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor >isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >arg : T | T[] ->arg.push(null as any as T) : number +>arg.push(t) : number >arg.push : (...items: T[]) => number >arg : T[] >push : (...items: T[]) => number ->null as any as T : T ->null as any : any ->null : null +>t : T } -function fn13(arg: T | ReadonlyArray) { ->fn13 : (arg: T | readonly T[]) => void +function fn13(arg: T | ReadonlyArray, t: T) { +>fn13 : (arg: T | readonly T[], t: T) => void >arg : T | readonly T[] +>t : T - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + if (Array.isArray(arg)) arg.push(t); // Should fail >Array.isArray(arg) : boolean >Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor >isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >arg : T | readonly T[] ->arg.push(null as any as T) : any +>arg.push(t) : any >arg.push : any >arg : readonly T[] >push : any ->null as any as T : T ->null as any : any ->null : null +>t : T - if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK + if (Array.isArray(arg)) arg.indexOf(t); // OK >Array.isArray(arg) : boolean >Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor >isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >arg : T | readonly T[] ->arg.indexOf(null as any as T) : number +>arg.indexOf(t) : number >arg.indexOf : (searchElement: T, fromIndex?: number | undefined) => number >arg : readonly T[] >indexOf : (searchElement: T, fromIndex?: number | undefined) => number ->null as any as T : T ->null as any : any ->null : null +>t : T } function fn14(arg: T | [T]) { @@ -357,37 +352,34 @@ function fn14(arg: T | [T]) { >null : null } -function fn15(arg: T | readonly [T]) { ->fn15 : (arg: T | readonly [T]) => void +function fn15(arg: T | readonly [T], t: T) { +>fn15 : (arg: T | readonly [T], t: T) => void >arg : T | readonly [T] +>t : T - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail + if (Array.isArray(arg)) arg.push(t); // Should fail >Array.isArray(arg) : boolean >Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor >isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >arg : T | readonly [T] ->arg.push(null as any as T) : any +>arg.push(t) : any >arg.push : any >arg : readonly [T] >push : any ->null as any as T : T ->null as any : any ->null : null +>t : T - if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK + if (Array.isArray(arg)) arg.indexOf(t); // Should OK >Array.isArray(arg) : boolean >Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor >isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >arg : T | readonly [T] ->arg.indexOf(null as any as T) : number +>arg.indexOf(t) : number >arg.indexOf : (searchElement: T, fromIndex?: number | undefined) => number >arg : readonly [T] >indexOf : (searchElement: T, fromIndex?: number | undefined) => number ->null as any as T : T ->null as any : any ->null : null +>t : T } function fn16(arg: T) { diff --git a/tests/cases/compiler/isArray.ts b/tests/cases/compiler/isArray.ts index efc954acb0601..1f00a17292c7b 100644 --- a/tests/cases/compiler/isArray.ts +++ b/tests/cases/compiler/isArray.ts @@ -30,8 +30,8 @@ function fn6(arg: string | string[]) { if (Array.isArray(arg)) arg.push(10); // Should FAIL } -function fn7(arg: boolean | number[] | string[]) { - if (Array.isArray(arg)) arg.push(null as any as string & number); // Should OK +function fn7(arg: boolean | number[] | string[], stringAndNumber: string & number) { + if (Array.isArray(arg)) arg.push(stringAndNumber); // Should OK } function fn8(arg: string | number[] | readonly string[]) { @@ -55,22 +55,22 @@ function fn11(arg: string | MyReadOnlyArray) { if (Array.isArray(arg)) arg.manifest; // Should OK } -function fn12(arg: T | T[]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +function fn12(arg: T | T[], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should OK } -function fn13(arg: T | ReadonlyArray) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail - if (Array.isArray(arg)) arg.indexOf(null as any as T); // OK +function fn13(arg: T | ReadonlyArray, t: T) { + if (Array.isArray(arg)) arg.push(t); // Should fail + if (Array.isArray(arg)) arg.indexOf(t); // OK } function fn14(arg: T | [T]) { if (Array.isArray(arg)) arg.push(null as any as T); // Should OK } -function fn15(arg: T | readonly [T]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should fail - if (Array.isArray(arg)) arg.indexOf(null as any as T); // Should OK +function fn15(arg: T | readonly [T], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should fail + if (Array.isArray(arg)) arg.indexOf(t); // Should OK } function fn16(arg: T) { From 5e54de0ef6659e0046fb4e0cb4f9e5c6a09877d4 Mon Sep 17 00:00:00 2001 From: Ulrich Buchgraber Date: Wed, 17 Jul 2019 04:15:53 +0200 Subject: [PATCH 5/6] Add additional negative tests --- tests/baselines/reference/isArray.errors.txt | 8 +++++- tests/baselines/reference/isArray.js | 5 +++- tests/baselines/reference/isArray.symbols | 26 +++++++++++++++----- tests/baselines/reference/isArray.types | 21 +++++++++++++++- tests/cases/compiler/isArray.ts | 4 ++- 5 files changed, 54 insertions(+), 10 deletions(-) diff --git a/tests/baselines/reference/isArray.errors.txt b/tests/baselines/reference/isArray.errors.txt index 8bf12aa3563c6..7381d65987b85 100644 --- a/tests/baselines/reference/isArray.errors.txt +++ b/tests/baselines/reference/isArray.errors.txt @@ -112,11 +112,17 @@ tests/cases/compiler/isArray.ts(83,15): error TS2345: Argument of type '"str"' i function fn16(arg: T) { if (Array.isArray(arg)) arg.push("10"); // Should OK + if (Array.isArray(arg)) arg.push(10); // Should fail + ~~ +!!! error TS2345: Argument of type '10' is not assignable to parameter of type 'string'. } function fn17() { const s: Array = []; const arrs = s.filter(Array.isArray); - arrs.push(["one"]); + arrs.push(["one"]); // Should OK + arrs.push("str"); // Should fail + ~~~~~ +!!! error TS2345: Argument of type '"str"' is not assignable to parameter of type 'string[]'. } \ No newline at end of file diff --git a/tests/baselines/reference/isArray.js b/tests/baselines/reference/isArray.js index 7fb61313f91d9..04e5fe97d3f78 100644 --- a/tests/baselines/reference/isArray.js +++ b/tests/baselines/reference/isArray.js @@ -169,9 +169,12 @@ function fn15(arg, t) { function fn16(arg) { if (Array.isArray(arg)) arg.push("10"); // Should OK + if (Array.isArray(arg)) + arg.push(10); // Should fail } function fn17() { var s = []; var arrs = s.filter(Array.isArray); - arrs.push(["one"]); + arrs.push(["one"]); // Should OK + arrs.push("str"); // Should fail } diff --git a/tests/baselines/reference/isArray.symbols b/tests/baselines/reference/isArray.symbols index 3c7507759b417..9bd7c65db04f5 100644 --- a/tests/baselines/reference/isArray.symbols +++ b/tests/baselines/reference/isArray.symbols @@ -342,28 +342,42 @@ function fn16(arg: T) { >arg : Symbol(arg, Decl(isArray.ts, 73, 43)) >arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(isArray.ts, 73, 43)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + if (Array.isArray(arg)) arg.push(10); // Should fail +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 73, 43)) +>arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(isArray.ts, 73, 43)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } function fn17() { ->fn17 : Symbol(fn17, Decl(isArray.ts, 75, 1)) +>fn17 : Symbol(fn17, Decl(isArray.ts, 76, 1)) const s: Array = []; ->s : Symbol(s, Decl(isArray.ts, 78, 9)) +>s : Symbol(s, Decl(isArray.ts, 79, 9)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) const arrs = s.filter(Array.isArray); ->arrs : Symbol(arrs, Decl(isArray.ts, 79, 9)) +>arrs : Symbol(arrs, Decl(isArray.ts, 80, 9)) >s.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->s : Symbol(s, Decl(isArray.ts, 78, 9)) +>s : Symbol(s, Decl(isArray.ts, 79, 9)) >filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) - arrs.push(["one"]); + arrs.push(["one"]); // Should OK +>arrs.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arrs : Symbol(arrs, Decl(isArray.ts, 80, 9)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + arrs.push("str"); // Should fail >arrs.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->arrs : Symbol(arrs, Decl(isArray.ts, 79, 9)) +>arrs : Symbol(arrs, Decl(isArray.ts, 80, 9)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } diff --git a/tests/baselines/reference/isArray.types b/tests/baselines/reference/isArray.types index 2dbaec499de43..4b53e3a268f9b 100644 --- a/tests/baselines/reference/isArray.types +++ b/tests/baselines/reference/isArray.types @@ -397,6 +397,18 @@ function fn16(arg: T) { >arg : T extends readonly any[] ? T : any[] extends T ? T & any[] : never >push : (...items: string[]) => number >"10" : "10" + + if (Array.isArray(arg)) arg.push(10); // Should fail +>Array.isArray(arg) : boolean +>Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>Array : ArrayConstructor +>isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>arg : T +>arg.push(10) : number +>arg.push : (...items: string[]) => number +>arg : T extends readonly any[] ? T : any[] extends T ? T & any[] : never +>push : (...items: string[]) => number +>10 : 10 } function fn17() { @@ -416,12 +428,19 @@ function fn17() { >Array : ArrayConstructor >isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never - arrs.push(["one"]); + arrs.push(["one"]); // Should OK >arrs.push(["one"]) : number >arrs.push : (...items: string[][]) => number >arrs : string[][] >push : (...items: string[][]) => number >["one"] : string[] >"one" : "one" + + arrs.push("str"); // Should fail +>arrs.push("str") : number +>arrs.push : (...items: string[][]) => number +>arrs : string[][] +>push : (...items: string[][]) => number +>"str" : "str" } diff --git a/tests/cases/compiler/isArray.ts b/tests/cases/compiler/isArray.ts index 1f00a17292c7b..4baa168773ced 100644 --- a/tests/cases/compiler/isArray.ts +++ b/tests/cases/compiler/isArray.ts @@ -75,10 +75,12 @@ function fn15(arg: T | readonly [T], t: T) { function fn16(arg: T) { if (Array.isArray(arg)) arg.push("10"); // Should OK + if (Array.isArray(arg)) arg.push(10); // Should fail } function fn17() { const s: Array = []; const arrs = s.filter(Array.isArray); - arrs.push(["one"]); + arrs.push(["one"]); // Should OK + arrs.push("str"); // Should fail } From 88cd932b269338933bf3446c5ad4622b42ede007 Mon Sep 17 00:00:00 2001 From: Ulrich Buchgraber Date: Wed, 17 Jul 2019 04:24:31 +0200 Subject: [PATCH 6/6] Fix leftover test type cast --- tests/baselines/reference/isArray.errors.txt | 4 ++-- tests/baselines/reference/isArray.js | 8 ++++---- tests/baselines/reference/isArray.symbols | 8 +++++--- tests/baselines/reference/isArray.types | 13 ++++++------- tests/cases/compiler/isArray.ts | 4 ++-- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/tests/baselines/reference/isArray.errors.txt b/tests/baselines/reference/isArray.errors.txt index 7381d65987b85..558c6b042be0c 100644 --- a/tests/baselines/reference/isArray.errors.txt +++ b/tests/baselines/reference/isArray.errors.txt @@ -99,8 +99,8 @@ tests/cases/compiler/isArray.ts(83,15): error TS2345: Argument of type '"str"' i if (Array.isArray(arg)) arg.indexOf(t); // OK } - function fn14(arg: T | [T]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK + function fn14(arg: T | [T], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should OK } function fn15(arg: T | readonly [T], t: T) { diff --git a/tests/baselines/reference/isArray.js b/tests/baselines/reference/isArray.js index 04e5fe97d3f78..e52ad526d7508 100644 --- a/tests/baselines/reference/isArray.js +++ b/tests/baselines/reference/isArray.js @@ -63,8 +63,8 @@ function fn13(arg: T | ReadonlyArray, t: T) { if (Array.isArray(arg)) arg.indexOf(t); // OK } -function fn14(arg: T | [T]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +function fn14(arg: T | [T], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should OK } function fn15(arg: T | readonly [T], t: T) { @@ -156,9 +156,9 @@ function fn13(arg, t) { if (Array.isArray(arg)) arg.indexOf(t); // OK } -function fn14(arg) { +function fn14(arg, t) { if (Array.isArray(arg)) - arg.push(null); // Should OK + arg.push(t); // Should OK } function fn15(arg, t) { if (Array.isArray(arg)) diff --git a/tests/baselines/reference/isArray.symbols b/tests/baselines/reference/isArray.symbols index 9bd7c65db04f5..04a2fc1258f9b 100644 --- a/tests/baselines/reference/isArray.symbols +++ b/tests/baselines/reference/isArray.symbols @@ -283,14 +283,16 @@ function fn13(arg: T | ReadonlyArray, t: T) { >t : Symbol(t, Decl(isArray.ts, 59, 43)) } -function fn14(arg: T | [T]) { +function fn14(arg: T | [T], t: T) { >fn14 : Symbol(fn14, Decl(isArray.ts, 62, 1)) >T : Symbol(T, Decl(isArray.ts, 64, 14)) >arg : Symbol(arg, Decl(isArray.ts, 64, 17)) >T : Symbol(T, Decl(isArray.ts, 64, 14)) +>T : Symbol(T, Decl(isArray.ts, 64, 14)) +>t : Symbol(t, Decl(isArray.ts, 64, 30)) >T : Symbol(T, Decl(isArray.ts, 64, 14)) - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK + if (Array.isArray(arg)) arg.push(t); // Should OK >Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) @@ -298,7 +300,7 @@ function fn14(arg: T | [T]) { >arg.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) >arg : Symbol(arg, Decl(isArray.ts, 64, 17)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(isArray.ts, 64, 14)) +>t : Symbol(t, Decl(isArray.ts, 64, 30)) } function fn15(arg: T | readonly [T], t: T) { diff --git a/tests/baselines/reference/isArray.types b/tests/baselines/reference/isArray.types index 4b53e3a268f9b..71a9af0a866ff 100644 --- a/tests/baselines/reference/isArray.types +++ b/tests/baselines/reference/isArray.types @@ -333,23 +333,22 @@ function fn13(arg: T | ReadonlyArray, t: T) { >t : T } -function fn14(arg: T | [T]) { ->fn14 : (arg: T | [T]) => void +function fn14(arg: T | [T], t: T) { +>fn14 : (arg: T | [T], t: T) => void >arg : T | [T] +>t : T - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK + if (Array.isArray(arg)) arg.push(t); // Should OK >Array.isArray(arg) : boolean >Array.isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >Array : ArrayConstructor >isArray : (arg: T) => arg is T extends readonly any[] ? T : any[] extends T ? T & any[] : never >arg : T | [T] ->arg.push(null as any as T) : number +>arg.push(t) : number >arg.push : (...items: T[]) => number >arg : [T] >push : (...items: T[]) => number ->null as any as T : T ->null as any : any ->null : null +>t : T } function fn15(arg: T | readonly [T], t: T) { diff --git a/tests/cases/compiler/isArray.ts b/tests/cases/compiler/isArray.ts index 4baa168773ced..756634e12f80f 100644 --- a/tests/cases/compiler/isArray.ts +++ b/tests/cases/compiler/isArray.ts @@ -64,8 +64,8 @@ function fn13(arg: T | ReadonlyArray, t: T) { if (Array.isArray(arg)) arg.indexOf(t); // OK } -function fn14(arg: T | [T]) { - if (Array.isArray(arg)) arg.push(null as any as T); // Should OK +function fn14(arg: T | [T], t: T) { + if (Array.isArray(arg)) arg.push(t); // Should OK } function fn15(arg: T | readonly [T], t: T) {