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/genericFunctionsAndConditionalInference.ts === 20declare function AssertType(value:any, type:string):void; 21type Boxified<T> = { [P in keyof T]: { value: T[P]} }; 22 23declare function unboxify<T>(obj: Boxified<T>): T; 24 25function foo<U, V>(obj: { u: { value: U }, v: { value: V } }) { 26AssertType(unboxify(obj), "{ u: U; v: V; }"); 27AssertType(unboxify, "<T>(Boxified<T>) => T"); 28AssertType(obj, "{ u: { value: U; }; v: { value: V; }; }"); 29 return unboxify(obj); 30} 31 32let qq = foo({ u: { value: 10 }, v: { value: 'hello'} }); // { u: U, v: V } but should be { u: number, v: string 33AssertType(qq, "{ u: number; v: string; }"); 34 35AssertType(foo({ u: { value: 10 }, v: { value: 'hello'} }), "{ u: number; v: string; }"); 36 37AssertType(foo, "<U, V>({ u: { value: U; }; v: { value: V; }; }) => { u: U; v: V; }"); 38 39AssertType({ u: { value: 10 }, v: { value: 'hello'} }, "{ u: { value: number; }; v: { value: string; }; }"); 40 41AssertType(u, "{ value: number; }"); 42 43AssertType({ value: 10 }, "{ value: number; }"); 44 45AssertType(value, "number"); 46 47AssertType(10, "int"); 48 49AssertType(v, "{ value: string; }"); 50 51AssertType({ value: 'hello'}, "{ value: string; }"); 52 53AssertType(value, "string"); 54 55AssertType('hello', "string"); 56} 57 58// From #42385 59interface Targets<A> { 60 left: A 61 right: A 62} 63type Target = keyof Targets<any> 64type Result<F extends Target, A> = Targets<A>[F] 65 66type LR<F extends Target, L, R> = [F] extends ["left"] ? L : R 67 68interface Ops<F extends Target> { 69 _f: F 70 str: Result<F, string> 71 num: Result<F, number> 72 lr<I, O>(a: Result<F, I>, o: Result<F, O>): Result<F, LR<F, I, O>> 73 dict: <P>(p: {[k in keyof P]: Result<F, P[k]>}) => Result<F, P> 74} 75const left: Ops<"left"> = {} as any 76AssertType(left, "Ops<"left">"); 77AssertType({} as any, "any"); 78AssertType({}, "{}"); 79 80const right: Ops<"right"> = {} as any 81AssertType(right, "Ops<"right">"); 82AssertType({} as any, "any"); 83AssertType({}, "{}"); 84 85const ok = <F extends Target>(at: Ops<F>) => ({lr: at.lr(at.str, at.num)}) 86AssertType(ok, "<F extends keyof Targets<any>>(Ops<F>) => { lr: Result<F, LR<F, string, number>>; }"); 87AssertType(<F extends Target>(at: Ops<F>) => ({lr: at.lr(at.str, at.num)}), "<F extends keyof Targets<any>>(Ops<F>) => { lr: Result<F, LR<F, string, number>>; }"); 88AssertType(at, "Ops<F>"); 89AssertType(({lr: at.lr(at.str, at.num)}), "{ lr: Result<F, LR<F, string, number>>; }"); 90AssertType({lr: at.lr(at.str, at.num)}, "{ lr: Result<F, LR<F, string, number>>; }"); 91AssertType(lr, "Result<F, LR<F, string, number>>"); 92AssertType(at.lr(at.str, at.num), "Result<F, LR<F, string, number>>"); 93AssertType(at.lr, "<I, O>(Result<F, I>, Result<F, O>) => Result<F, LR<F, I, O>>"); 94AssertType(at.str, "Result<F, string>"); 95AssertType(at.num, "Result<F, number>"); 96 97const orphaned = <F extends Target>(at: Ops<F>) => at.dict(ok(at)) 98AssertType(orphaned, "<F extends keyof Targets<any>>(Ops<F>) => Result<F, { lr: LR<F, string, number>; }>"); 99AssertType(<F extends Target>(at: Ops<F>) => at.dict(ok(at)), "<F extends keyof Targets<any>>(Ops<F>) => Result<F, { lr: LR<F, string, number>; }>"); 100AssertType(at, "Ops<F>"); 101AssertType(at.dict(ok(at)), "Result<F, { lr: LR<F, string, number>; }>"); 102AssertType(at.dict, "<P>({ [k in keyof P]: Result<F, P[k]>; }) => Result<F, P>"); 103AssertType(ok(at), "{ lr: Result<F, LR<F, string, number>>; }"); 104AssertType(ok, "<F extends keyof Targets<any>>(Ops<F>) => { lr: Result<F, LR<F, string, number>>; }"); 105AssertType(at, "Ops<F>"); 106 107const leftOk = ok(left) 108AssertType(leftOk, "{ lr: string; }"); 109AssertType(ok(left), "{ lr: string; }"); 110AssertType(ok, "<F extends keyof Targets<any>>(Ops<F>) => { lr: Result<F, LR<F, string, number>>; }"); 111AssertType(left, "Ops<"left">"); 112 113const leftOrphaned = orphaned(left) 114AssertType(leftOrphaned, "{ lr: string; }"); 115AssertType(orphaned(left), "{ lr: string; }"); 116AssertType(orphaned, "<F extends keyof Targets<any>>(Ops<F>) => Result<F, { lr: LR<F, string, number>; }>"); 117AssertType(left, "Ops<"left">"); 118 119const rightOk = ok(right) 120AssertType(rightOk, "{ lr: number; }"); 121AssertType(ok(right), "{ lr: number; }"); 122AssertType(ok, "<F extends keyof Targets<any>>(Ops<F>) => { lr: Result<F, LR<F, string, number>>; }"); 123AssertType(right, "Ops<"right">"); 124 125const rightOrphaned = orphaned(right) 126AssertType(rightOrphaned, "{ lr: number; }"); 127AssertType(orphaned(right), "{ lr: number; }"); 128AssertType(orphaned, "<F extends keyof Targets<any>>(Ops<F>) => Result<F, { lr: LR<F, string, number>; }>"); 129AssertType(right, "Ops<"right">"); 130 131 132