1/* 2* Copyright (c) Microsoft Corporation. All rights reserved. 3* Copyright (c) 2023 Huawei Device Co., Ltd. 4* Licensed under the Apache License, Version 2.0 (the "License"); 5* you may not use this file except in compliance with the License. 6* You may obtain a copy of the License at 7* 8* http://www.apache.org/licenses/LICENSE-2.0 9* 10* Unless required by applicable law or agreed to in writing, software 11* distributed under the License is distributed on an "AS IS" BASIS, 12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13* See the License for the specific language governing permissions and 14* limitations under the License. 15* 16* This file has been modified by Huawei to verify type inference by adding verification statements. 17*/ 18 19// === tests/cases/compiler/narrowingAssignmentReadonlyRespectsAssertion.ts === 20declare function AssertType(value:any, type:string):void; 21// https://github.com/microsoft/TypeScript/issues/41984 22 23interface TestCase<T extends string | number> { 24 readonly val1: T | ReadonlyArray<T>; 25 readonly val2: ReadonlyArray<T>; 26} 27 28interface MultiCaseFixture<T> { 29 cases: T[]; 30} 31 32function subDataFunc(): TestCase<string | number>[] { 33AssertType([ { 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] }, ], "(union)[]"); 34 return [ 35 36 { val1: "a", val2: ["a", "b", "c"] }, 37AssertType({ val1: "a", val2: ["a", "b", "c"] }, "{ val1: string; val2: string[]; }"); 38AssertType(val1, "string"); 39AssertType("a", "string"); 40AssertType(val2, "string[]"); 41AssertType(["a", "b", "c"], "string[]"); 42AssertType("a", "string"); 43AssertType("b", "string"); 44AssertType("c", "string"); 45 46 { val1: 2, val2: [1, 2, 3] }, 47AssertType({ val1: 2, val2: [1, 2, 3] }, "{ val1: number; val2: number[]; }"); 48AssertType(val1, "number"); 49AssertType(2, "int"); 50AssertType(val2, "number[]"); 51AssertType([1, 2, 3], "number[]"); 52AssertType(1, "int"); 53AssertType(2, "int"); 54AssertType(3, "int"); 55 56 { val1: ["a", "z"], val2: ["x", "y", "z"] }, 57AssertType({ val1: ["a", "z"], val2: ["x", "y", "z"] }, "{ val1: string[]; val2: string[]; }"); 58AssertType(val1, "string[]"); 59AssertType(["a", "z"], "string[]"); 60AssertType("a", "string"); 61AssertType("z", "string"); 62AssertType(val2, "string[]"); 63AssertType(["x", "y", "z"], "string[]"); 64AssertType("x", "string"); 65AssertType("y", "string"); 66AssertType("z", "string"); 67 68 { val1: [5, 10], val2: [10, 100, 1000] }, 69AssertType({ val1: [5, 10], val2: [10, 100, 1000] }, "{ val1: number[]; val2: number[]; }"); 70AssertType(val1, "number[]"); 71AssertType([5, 10], "number[]"); 72AssertType(5, "int"); 73AssertType(10, "int"); 74AssertType(val2, "number[]"); 75AssertType([10, 100, 1000], "number[]"); 76AssertType(10, "int"); 77AssertType(100, "int"); 78AssertType(1000, "int"); 79 80 ]; 81} 82 83function dataFunc<T>(subFunc: () => T[]): MultiCaseFixture<T> { 84AssertType({ cases: subFunc() }, "{ cases: T[]; }"); 85AssertType(cases, "T[]"); 86AssertType(subFunc(), "T[]"); 87AssertType(subFunc, "() => T[]"); 88 return { cases: subFunc() }; 89} 90 91function testFunc() { 92 const fixture = dataFunc<TestCase<string | number>>(subDataFunc); 93AssertType(fixture, "MultiCaseFixture<TestCase<union>>"); 94AssertType(dataFunc<TestCase<string | number>>(subDataFunc), "MultiCaseFixture<TestCase<union>>"); 95AssertType(dataFunc, "<T>(() => T[]) => MultiCaseFixture<T>"); 96AssertType(subDataFunc, "() => TestCase<union>[]"); 97 98 fixture.cases.forEach(({ val1, val2 }) => { 99AssertType(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"); 100AssertType(fixture.cases.forEach, "((TestCase<union>, number, TestCase<union>[]) => void, ?any) => void"); 101AssertType(fixture.cases, "TestCase<union>[]"); 102AssertType(({ 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); }, "(TestCase<union>) => void"); 103AssertType(val1, "union"); 104AssertType(val2, "readonly (union)[]"); 105 106 if (Array.isArray(val1)) { 107AssertType(Array.isArray(val1), "boolean"); 108AssertType(Array.isArray, "(any) => arg is any[]"); 109AssertType(val1, "union"); 110 111 // This should retain val1 as being an array 112 const reversedVal1 = val1.slice().reverse(); 113AssertType(reversedVal1, "any[]"); 114AssertType(val1.slice().reverse(), "any[]"); 115AssertType(val1.slice().reverse, "() => any[]"); 116AssertType(val1.slice(), "any[]"); 117AssertType(val1.slice, "(?number, ?number) => any[]"); 118 119 console.log(reversedVal1); 120AssertType(console.log(reversedVal1), "void"); 121AssertType(console.log, "(...any[]) => void"); 122AssertType(reversedVal1, "any[]"); 123 124 } else { 125 console.log(val1); 126AssertType(console.log(val1), "void"); 127AssertType(console.log, "(...any[]) => void"); 128AssertType(val1, "union"); 129 } 130 console.log(val2); 131AssertType(console.log(val2), "void"); 132AssertType(console.log, "(...any[]) => void"); 133AssertType(val2, "readonly (union)[]"); 134 135 }); 136} 137 138testFunc(); 139AssertType(testFunc(), "void"); 140AssertType(testFunc, "() => void"); 141 142 143