• 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/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