1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16function foo(x: "a"|"b"|"c") {
17    x = "c"
18    return x
19}
20
21function id<T>(v: Object): T {
22    return v as T
23}
24
25function getColor(colors: Array<"default"|"invisible"|number>, id: number) {
26    return colors[id]
27}
28
29function f1(a: "xyz"): "xyz" {
30    return a
31}
32
33function f2(a: "aa"|"bb"): "aa"|"bb" {
34    return a
35}
36
37function f3(a: "aa"|"bb") {
38    return a + "cc"
39}
40
41function f4(a: "b"): "b" {
42    return a
43}
44
45class A {
46    p: "aa"|"bb" = "bb"
47}
48
49function test_inference_from_return() {
50    let arr = new Array<"default"|"invisible"|number>(3);
51    arr[0] = "default"
52    arr[1] = 42
53    arr[2] = "invisible"
54    let s = getColor(arr, 0)   // s is of type string|number
55    assert s == "default"
56    s = "dd"
57}
58
59function test_inference_from_conditional(cond: boolean) {
60    let x1 = cond ? "aa" : "bb"  // type of x1 is string
61    assert x1 == "aa"
62    x1 = "abc"
63    assert x1 == "abc"
64    let x2: "yes"|"no" = cond ? "yes" : "no"
65    assert x2 == "yes"
66    let x3 = cond ? "one" : new A  // type of x3 is string|A
67    assert x3 == "one"
68    x3 = "bb"
69    assert x3 == "bb"
70
71    const x4 = cond ? "aa" : "bb"  // type of x4 is "aa"|"bb"
72    let y4 = f2(x4)  // type of y4 is "aa"|"bb"
73    let z4 = f2(y4)
74    assert z4 == "aa"
75
76    let x5 = ((p: boolean) => p ? "bb" : "aa")(cond)  // type of x5 is string
77    assert x5 == "bb"
78    x5 = "xyz"
79    assert x5 == "xyz"
80}
81
82function main() {
83    const x1 = "xyz"
84    let y1 = f1(x1)
85    assert y1 == "xyz"
86
87    let s = id<"a"|"b"|"c">("b")  // type of s is "a"|"b"|"c"
88    assert s == "b"
89    assert s != "a"
90    assert foo(s) == "c"
91    let y = s as "b"
92    assert y == "b"
93    assert f4(s as "b") == "b"
94
95    test_inference_from_conditional(true)
96    test_inference_from_return()
97
98    assert f3("aa") == "aacc"
99
100    let a = new A
101    let x2 = a.p
102    assert f2(x2) == "bb"
103    let z = x2
104    assert f2(z) == "bb"
105
106    let x3: ("aa"|"bb")[] = ["aa", "bb", "aa"]
107    let y3 = f2(x3[0])  // type of y3 is "aa"|"bb"
108    assert y3 == "aa"
109    assert x3[1] == "bb"
110
111    let x4 = ["aa", "bb", "aa", 43]  // type of x4 is (string|int)[]
112    x4[0] = "cc"
113    assert x4[0] == "cc"
114    assert x4[1] == "bb"
115    x4[2] = 55
116    x4[3] = "xyz"
117    assert x4[2] == 55
118    assert x4[3] == "xyz"
119}
120