diff --git a/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.js b/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.js new file mode 100644 index 0000000000000..5db0ab74ca7ae --- /dev/null +++ b/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.js @@ -0,0 +1,71 @@ +//// [narrowingAssignmentReadonlyRespectsAssertion.ts] +// https://github.com/microsoft/TypeScript/issues/41984 + +interface TestCase { + readonly val1: T | ReadonlyArray; + readonly val2: ReadonlyArray; +} + +interface MultiCaseFixture { + cases: T[]; +} + +function subDataFunc(): TestCase[] { + return [ + { val1: "a", val2: ["a", "b", "c"] }, + { val1: 2, val2: [1, 2, 3] }, + { val1: ["a", "z"], val2: ["x", "y", "z"] }, + { val1: [5, 10], val2: [10, 100, 1000] }, + ]; +} + +function dataFunc(subFunc: () => T[]): MultiCaseFixture { + return { cases: subFunc() }; +} + +function testFunc() { + const fixture = dataFunc>(subDataFunc); + fixture.cases.forEach(({ val1, val2 }) => { + if (Array.isArray(val1)) { + // This should retain val1 as being an array + const reversedVal1 = val1.slice().reverse(); + console.log(reversedVal1); + } else { + console.log(val1); + } + console.log(val2); + }); +} + +testFunc(); + + +//// [narrowingAssignmentReadonlyRespectsAssertion.js] +// https://github.com/microsoft/TypeScript/issues/41984 +function subDataFunc() { + return [ + { val1: "a", val2: ["a", "b", "c"] }, + { val1: 2, val2: [1, 2, 3] }, + { val1: ["a", "z"], val2: ["x", "y", "z"] }, + { val1: [5, 10], val2: [10, 100, 1000] }, + ]; +} +function dataFunc(subFunc) { + return { cases: subFunc() }; +} +function testFunc() { + var fixture = dataFunc(subDataFunc); + fixture.cases.forEach(function (_a) { + var val1 = _a.val1, val2 = _a.val2; + if (Array.isArray(val1)) { + // This should retain val1 as being an array + var reversedVal1 = val1.slice().reverse(); + console.log(reversedVal1); + } + else { + console.log(val1); + } + console.log(val2); + }); +} +testFunc(); diff --git a/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.symbols b/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.symbols new file mode 100644 index 0000000000000..8b7fcfebae44f --- /dev/null +++ b/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.symbols @@ -0,0 +1,123 @@ +=== tests/cases/compiler/narrowingAssignmentReadonlyRespectsAssertion.ts === +// https://github.com/microsoft/TypeScript/issues/41984 + +interface TestCase { +>TestCase : Symbol(TestCase, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 0, 0)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 19)) + + readonly val1: T | ReadonlyArray; +>val1 : Symbol(TestCase.val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 47)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 19)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 19)) + + readonly val2: ReadonlyArray; +>val2 : Symbol(TestCase.val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 3, 38)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 2, 19)) +} + +interface MultiCaseFixture { +>MultiCaseFixture : Symbol(MultiCaseFixture, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 5, 1)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 27)) + + cases: T[]; +>cases : Symbol(MultiCaseFixture.cases, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 31)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 27)) +} + +function subDataFunc(): TestCase[] { +>subDataFunc : Symbol(subDataFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 9, 1)) +>TestCase : Symbol(TestCase, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 0, 0)) + + return [ + { val1: "a", val2: ["a", "b", "c"] }, +>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 13, 7)) +>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 13, 18)) + + { val1: 2, val2: [1, 2, 3] }, +>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 14, 7)) +>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 14, 16)) + + { val1: ["a", "z"], val2: ["x", "y", "z"] }, +>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 15, 7)) +>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 15, 25)) + + { val1: [5, 10], val2: [10, 100, 1000] }, +>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 16, 7)) +>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 16, 22)) + + ]; +} + +function dataFunc(subFunc: () => T[]): MultiCaseFixture { +>dataFunc : Symbol(dataFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 18, 1)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 18)) +>subFunc : Symbol(subFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 21)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 18)) +>MultiCaseFixture : Symbol(MultiCaseFixture, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 5, 1)) +>T : Symbol(T, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 18)) + + return { cases: subFunc() }; +>cases : Symbol(cases, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 21, 10)) +>subFunc : Symbol(subFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 20, 21)) +} + +function testFunc() { +>testFunc : Symbol(testFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 22, 1)) + + const fixture = dataFunc>(subDataFunc); +>fixture : Symbol(fixture, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 25, 7)) +>dataFunc : Symbol(dataFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 18, 1)) +>TestCase : Symbol(TestCase, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 0, 0)) +>subDataFunc : Symbol(subDataFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 9, 1)) + + fixture.cases.forEach(({ val1, val2 }) => { +>fixture.cases.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) +>fixture.cases : Symbol(MultiCaseFixture.cases, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 31)) +>fixture : Symbol(fixture, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 25, 7)) +>cases : Symbol(MultiCaseFixture.cases, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 7, 31)) +>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) +>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 26)) +>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 32)) + + if (Array.isArray(val1)) { +>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, --, --)) +>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 26)) + + // This should retain val1 as being an array + const reversedVal1 = val1.slice().reverse(); +>reversedVal1 : Symbol(reversedVal1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 29, 15)) +>val1.slice().reverse : Symbol(Array.reverse, Decl(lib.es5.d.ts, --, --)) +>val1.slice : Symbol(Array.slice, Decl(lib.es5.d.ts, --, --)) +>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 26)) +>slice : Symbol(Array.slice, Decl(lib.es5.d.ts, --, --)) +>reverse : Symbol(Array.reverse, Decl(lib.es5.d.ts, --, --)) + + console.log(reversedVal1); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>reversedVal1 : Symbol(reversedVal1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 29, 15)) + + } else { + console.log(val1); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>val1 : Symbol(val1, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 26)) + } + console.log(val2); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>val2 : Symbol(val2, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 26, 32)) + + }); +} + +testFunc(); +>testFunc : Symbol(testFunc, Decl(narrowingAssignmentReadonlyRespectsAssertion.ts, 22, 1)) + diff --git a/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.types b/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.types new file mode 100644 index 0000000000000..9fd13d661027a --- /dev/null +++ b/tests/baselines/reference/narrowingAssignmentReadonlyRespectsAssertion.types @@ -0,0 +1,147 @@ +=== tests/cases/compiler/narrowingAssignmentReadonlyRespectsAssertion.ts === +// https://github.com/microsoft/TypeScript/issues/41984 + +interface TestCase { + readonly val1: T | ReadonlyArray; +>val1 : T | readonly T[] + + readonly val2: ReadonlyArray; +>val2 : readonly T[] +} + +interface MultiCaseFixture { + cases: T[]; +>cases : T[] +} + +function subDataFunc(): TestCase[] { +>subDataFunc : () => TestCase[] + + return [ +>[ { val1: "a", val2: ["a", "b", "c"] }, { val1: 2, val2: [1, 2, 3] }, { val1: ["a", "z"], val2: ["x", "y", "z"] }, { val1: [5, 10], val2: [10, 100, 1000] }, ] : ({ val1: string; val2: string[]; } | { val1: number; val2: number[]; } | { val1: string[]; val2: string[]; } | { val1: number[]; val2: number[]; })[] + + { val1: "a", val2: ["a", "b", "c"] }, +>{ val1: "a", val2: ["a", "b", "c"] } : { val1: string; val2: string[]; } +>val1 : string +>"a" : "a" +>val2 : string[] +>["a", "b", "c"] : string[] +>"a" : "a" +>"b" : "b" +>"c" : "c" + + { val1: 2, val2: [1, 2, 3] }, +>{ val1: 2, val2: [1, 2, 3] } : { val1: number; val2: number[]; } +>val1 : number +>2 : 2 +>val2 : number[] +>[1, 2, 3] : number[] +>1 : 1 +>2 : 2 +>3 : 3 + + { val1: ["a", "z"], val2: ["x", "y", "z"] }, +>{ val1: ["a", "z"], val2: ["x", "y", "z"] } : { val1: string[]; val2: string[]; } +>val1 : string[] +>["a", "z"] : string[] +>"a" : "a" +>"z" : "z" +>val2 : string[] +>["x", "y", "z"] : string[] +>"x" : "x" +>"y" : "y" +>"z" : "z" + + { val1: [5, 10], val2: [10, 100, 1000] }, +>{ val1: [5, 10], val2: [10, 100, 1000] } : { val1: number[]; val2: number[]; } +>val1 : number[] +>[5, 10] : number[] +>5 : 5 +>10 : 10 +>val2 : number[] +>[10, 100, 1000] : number[] +>10 : 10 +>100 : 100 +>1000 : 1000 + + ]; +} + +function dataFunc(subFunc: () => T[]): MultiCaseFixture { +>dataFunc : (subFunc: () => T[]) => MultiCaseFixture +>subFunc : () => T[] + + return { cases: subFunc() }; +>{ cases: subFunc() } : { cases: T[]; } +>cases : T[] +>subFunc() : T[] +>subFunc : () => T[] +} + +function testFunc() { +>testFunc : () => void + + const fixture = dataFunc>(subDataFunc); +>fixture : MultiCaseFixture> +>dataFunc>(subDataFunc) : MultiCaseFixture> +>dataFunc : (subFunc: () => T[]) => MultiCaseFixture +>subDataFunc : () => TestCase[] + + fixture.cases.forEach(({ val1, val2 }) => { +>fixture.cases.forEach(({ val1, val2 }) => { if (Array.isArray(val1)) { // This should retain val1 as being an array const reversedVal1 = val1.slice().reverse(); console.log(reversedVal1); } else { console.log(val1); } console.log(val2); }) : void +>fixture.cases.forEach : (callbackfn: (value: TestCase, index: number, array: TestCase[]) => void, thisArg?: any) => void +>fixture.cases : TestCase[] +>fixture : MultiCaseFixture> +>cases : TestCase[] +>forEach : (callbackfn: (value: TestCase, index: number, array: TestCase[]) => void, thisArg?: any) => void +>({ val1, val2 }) => { if (Array.isArray(val1)) { // This should retain val1 as being an array const reversedVal1 = val1.slice().reverse(); console.log(reversedVal1); } else { console.log(val1); } console.log(val2); } : ({ val1, val2 }: TestCase) => void +>val1 : string | number | readonly (string | number)[] +>val2 : readonly (string | number)[] + + if (Array.isArray(val1)) { +>Array.isArray(val1) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>val1 : string | number | readonly (string | number)[] + + // This should retain val1 as being an array + const reversedVal1 = val1.slice().reverse(); +>reversedVal1 : any[] +>val1.slice().reverse() : any[] +>val1.slice().reverse : () => any[] +>val1.slice() : any[] +>val1.slice : (start?: number, end?: number) => any[] +>val1 : any[] +>slice : (start?: number, end?: number) => any[] +>reverse : () => any[] + + console.log(reversedVal1); +>console.log(reversedVal1) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>reversedVal1 : any[] + + } else { + console.log(val1); +>console.log(val1) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>val1 : string | number | readonly (string | number)[] + } + console.log(val2); +>console.log(val2) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>val2 : readonly (string | number)[] + + }); +} + +testFunc(); +>testFunc() : void +>testFunc : () => void + diff --git a/tests/cases/compiler/narrowingAssignmentReadonlyRespectsAssertion.ts b/tests/cases/compiler/narrowingAssignmentReadonlyRespectsAssertion.ts new file mode 100644 index 0000000000000..adc138d60d466 --- /dev/null +++ b/tests/cases/compiler/narrowingAssignmentReadonlyRespectsAssertion.ts @@ -0,0 +1,39 @@ +// https://github.com/microsoft/TypeScript/issues/41984 + +interface TestCase { + readonly val1: T | ReadonlyArray; + readonly val2: ReadonlyArray; +} + +interface MultiCaseFixture { + cases: T[]; +} + +function subDataFunc(): TestCase[] { + return [ + { val1: "a", val2: ["a", "b", "c"] }, + { val1: 2, val2: [1, 2, 3] }, + { val1: ["a", "z"], val2: ["x", "y", "z"] }, + { val1: [5, 10], val2: [10, 100, 1000] }, + ]; +} + +function dataFunc(subFunc: () => T[]): MultiCaseFixture { + return { cases: subFunc() }; +} + +function testFunc() { + const fixture = dataFunc>(subDataFunc); + fixture.cases.forEach(({ val1, val2 }) => { + if (Array.isArray(val1)) { + // This should retain val1 as being an array + const reversedVal1 = val1.slice().reverse(); + console.log(reversedVal1); + } else { + console.log(val1); + } + console.log(val2); + }); +} + +testFunc();