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