• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference1.ts ===
20declare function AssertType(value:any, type:string):void;
21// Repro from #2264
22
23interface Y { 'i am a very certain type': Y }
24let y: Y = <Y>undefined;
25AssertType(y, "Y");
26AssertType(<Y>undefined, "Y");
27AssertType(undefined, "undefined");
28
29function destructure<a, r>(
30    something: a | Y,
31    haveValue: (value: a) => r,
32    haveY: (value: Y) => r
33): r {
34AssertType(something === y ? haveY(y) : haveValue(<a>something), "r");
35AssertType(something === y, "boolean");
36AssertType(something, "union");
37AssertType(y, "Y");
38AssertType(haveY(y), "r");
39AssertType(haveY, "(Y) => r");
40AssertType(y, "Y");
41AssertType(haveValue(<a>something), "r");
42AssertType(haveValue, "(a) => r");
43AssertType(<a>something, "a");
44AssertType(something, "union");
45    return something === y ? haveY(y) : haveValue(<a>something);
46}
47
48let value = Math.random() > 0.5 ? 'hey!' : <Y>undefined;
49AssertType(value, "union");
50AssertType(Math.random() > 0.5 ? 'hey!' : <Y>undefined, "union");
51AssertType(Math.random() > 0.5, "boolean");
52AssertType(Math.random(), "number");
53AssertType(Math.random, "() => number");
54AssertType(0.5, "double");
55AssertType('hey!', "string");
56AssertType(<Y>undefined, "Y");
57AssertType(undefined, "undefined");
58
59let result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y
60AssertType(result, "string");
61AssertType(destructure(value, text => 'string', y => 'other one'), "string");
62AssertType(destructure, "<a, r>(union, (a) => r, (Y) => r) => r");
63AssertType(value, "union");
64AssertType(text => 'string', "(string) => string");
65AssertType(text, "string");
66AssertType('string', "string");
67AssertType(y => 'other one', "(Y) => string");
68AssertType(y, "Y");
69AssertType('other one', "string");
70
71// Repro from #4212
72
73function isVoid<a>(value: void | a): value is void {
74AssertType(undefined, "undefined");
75    return undefined;
76}
77
78function isNonVoid<a>(value: void | a) : value is a {
79AssertType(undefined, "undefined");
80    return undefined;
81}
82
83function foo1<a>(value: void|a): void {
84    if (isVoid(value)) {
85AssertType(isVoid(value), "boolean");
86AssertType(isVoid, "<a>(union) => value is void");
87AssertType(value, "union");
88
89        value; // value is void
90AssertType(value, "void");
91
92    } else {
93        value; // value is a
94AssertType(value, "a");
95    }
96}
97
98function baz1<a>(value: void|a): void {
99      if (isNonVoid(value)) {
100AssertType(isNonVoid(value), "boolean");
101AssertType(isNonVoid, "<a>(union) => value is a");
102AssertType(value, "union");
103
104          value; // value is a
105AssertType(value, "a");
106
107      } else {
108          value; // value is void
109AssertType(value, "void");
110      }
111}
112
113// Repro from #5417
114
115type Maybe<T> = T | void;
116
117function get<U>(x: U | void): U {
118AssertType(null, "null");
119   return null; // just an example
120}
121
122let foo: Maybe<string>;
123AssertType(foo, "Maybe<string>");
124
125get(foo).toUpperCase(); // Ok
126AssertType(get(foo).toUpperCase(), "string");
127AssertType(get(foo).toUpperCase, "() => string");
128
129// Repro from #5456
130
131interface Man {
132    walks: boolean;
133}
134
135interface Bear {
136    roars: boolean;
137}
138
139interface Pig {
140    oinks: boolean;
141}
142
143declare function pigify<T>(y: T & Bear): T & Pig;
144declare let mbp: Man & Bear;
145AssertType(mbp, "Man & Bear");
146
147pigify(mbp).oinks; // OK, mbp is treated as Pig
148AssertType(pigify(mbp).oinks, "boolean");
149
150pigify(mbp).walks; // Ok, mbp is treated as Man
151AssertType(pigify(mbp).walks, "boolean");
152
153// Repros from #29815
154
155interface ITest {
156  name: 'test'
157}
158
159const createTestAsync = (): Promise<ITest> => Promise.resolve().then(() => ({ name: 'test' }))
160AssertType(createTestAsync, "() => Promise<ITest>");
161AssertType((): Promise<ITest> => Promise.resolve().then(() => ({ name: 'test' })), "() => Promise<ITest>");
162AssertType(Promise.resolve().then(() => ({ name: 'test' })), "Promise<union>");
163AssertType(Promise.resolve().then, "<TResult1 = void, TResult2 = never>(?(void) => union, ?(any) => union) => Promise<union>");
164AssertType(() => ({ name: 'test' }), "() => { name: "test"; }");
165AssertType(({ name: 'test' }), "{ name: "test"; }");
166AssertType({ name: 'test' }, "{ name: "test"; }");
167AssertType(name, "string");
168AssertType('test', "string");
169
170const createTest = (): ITest => {
171AssertType(createTest, "() => ITest");
172AssertType((): ITest => {  return { name: 'test' }}, "() => ITest");
173
174AssertType({ name: 'test' }, "{ name: "test"; }");
175  return { name: 'test'
176
177AssertType(name, "string");
178
179AssertType('test', "string");
180}
181}
182
183declare function f1<T, U>(x: T | U): T | U;
184declare function f2<T, U>(x: T, y: U): T | U;
185
186let x1: string = f1('a');
187AssertType(x1, "string");
188AssertType(f1('a'), "string");
189AssertType(f1, "<T, U>(union) => union");
190AssertType('a', "string");
191
192let x2: string = f2('a', 'b');
193AssertType(x2, "string");
194AssertType(f2('a', 'b'), "union");
195AssertType(f2, "<T, U>(T, U) => union");
196AssertType('a', "string");
197AssertType('b', "string");
198
199// Repro from #30442
200
201const func = <T>() => {};
202AssertType(func, "<T>() => void");
203AssertType(<T>() => {}, "<T>() => void");
204
205const assign = <T, U>(a: T, b: U) => Object.assign(a, b);
206AssertType(assign, "<T, U>(T, U) => T & U");
207AssertType(<T, U>(a: T, b: U) => Object.assign(a, b), "<T, U>(T, U) => T & U");
208AssertType(a, "T");
209AssertType(b, "U");
210AssertType(Object.assign(a, b), "T & U");
211AssertType(Object.assign, "{ <T extends {}, U>(T, U): T & U; <T extends {}, U, V>(T, U, V): T & U & V; <T extends {}, U, V, W>(T, U, V, W): T & U & V & W; (object, ...any[]): any; }");
212AssertType(a, "T");
213AssertType(b, "U");
214
215const res: (() => void) & { func: any } = assign(() => {}, { func });
216AssertType(res, "(() => void) & { func: any; }");
217AssertType(func, "any");
218AssertType(assign(() => {}, { func }), "(() => void) & { func: <T>() => void; }");
219AssertType(assign, "<T, U>(T, U) => T & U");
220AssertType(() => {}, "() => void");
221AssertType({ func }, "{ func: <T>() => void; }");
222AssertType(func, "<T>() => void");
223
224
225