Skip to content

Commit 51ba26e

Browse files
committed
Add instantiation rules for reverse mapped types
1 parent 71d4ee5 commit 51ba26e

5 files changed

+339
-1
lines changed

src/compiler/checker.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14615,6 +14615,9 @@ namespace ts {
1461514615
if (checkType === wildcardType || extendsType === wildcardType) {
1461614616
return wildcardType;
1461714617
}
14618+
if (getObjectFlags(extendsType) & ObjectFlags.ReverseMapped) {
14619+
debugger;
14620+
}
1461814621
let combinedMapper: TypeMapper | undefined;
1461914622
if (root.inferTypeParameters) {
1462014623
const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None);
@@ -15740,6 +15743,9 @@ namespace ts {
1574015743
const newTypeArguments = instantiateTypes(resolvedTypeArguments, mapper);
1574115744
return newTypeArguments !== resolvedTypeArguments ? createNormalizedTypeReference((<TypeReference>type).target, newTypeArguments) : type;
1574215745
}
15746+
if (objectFlags & ObjectFlags.ReverseMapped) {
15747+
return instantiateReverseMappedType(type as ReverseMappedType, mapper);
15748+
}
1574315749
return getObjectTypeInstantiation(<TypeReference | AnonymousType | MappedType>type, mapper, aliasSymbol, aliasTypeArguments);
1574415750
}
1574515751
return type;
@@ -15790,6 +15796,26 @@ namespace ts {
1579015796
return type;
1579115797
}
1579215798

15799+
function instantiateReverseMappedType(type: ReverseMappedType, mapper: TypeMapper) {
15800+
const innerMappedType = instantiateType(type.mappedType, mapper);
15801+
if (!(getObjectFlags(innerMappedType) & ObjectFlags.Mapped)) {
15802+
return type;
15803+
}
15804+
const innerIndexType = instantiateType(type.constraintType, mapper);
15805+
if (!(innerIndexType.flags & TypeFlags.Index)) {
15806+
return type;
15807+
}
15808+
const instantiated = inferTypeForHomomorphicMappedType(
15809+
instantiateType(type.source, mapper),
15810+
innerMappedType as MappedType,
15811+
innerIndexType as IndexType
15812+
);
15813+
if (instantiated) {
15814+
return instantiated;
15815+
}
15816+
return type; // Nested invocation of `inferTypeForHomomorphicMappedType` or the `source` instantiated into something unmappable
15817+
}
15818+
1579315819
function getPermissiveInstantiation(type: Type) {
1579415820
return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type :
1579515821
type.permissiveInstantiation || (type.permissiveInstantiation = instantiateType(type, permissiveMapper));
@@ -20147,7 +20173,7 @@ namespace ts {
2014720173
type.flags & TypeFlags.Object && !isNonGenericTopLevelType(type) && (
2014820174
objectFlags & ObjectFlags.Reference && ((<TypeReference>type).node || forEach(getTypeArguments(<TypeReference>type), couldContainTypeVariables)) ||
2014920175
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ||
20150-
objectFlags & (ObjectFlags.Mapped | ObjectFlags.ObjectRestType)) ||
20176+
objectFlags & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType)) ||
2015120177
type.flags & TypeFlags.UnionOrIntersection && !(type.flags & TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) && some((<UnionOrIntersectionType>type).types, couldContainTypeVariables));
2015220178
if (type.flags & TypeFlags.ObjectFlagsType) {
2015320179
(<ObjectFlagsType>type).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed | (result ? ObjectFlags.CouldContainTypeVariables : 0);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//// [genericFunctionsAndConditionalInference.ts]
2+
interface Targets<A> {
3+
left: A
4+
right: A
5+
}
6+
type Target = keyof Targets<any>
7+
type Result<F extends Target, A> = Targets<A>[F]
8+
9+
type LR<F extends Target, L, R> = [F] extends ["left"] ? L : R
10+
11+
interface Ops<F extends Target> {
12+
_f: F
13+
str: Result<F, string>
14+
num: Result<F, number>
15+
lr<I, O>(a: Result<F, I>, o: Result<F, O>): Result<F, LR<F, I, O>>
16+
dict: <P>(p: {[k in keyof P]: Result<F, P[k]>}) => Result<F, P>
17+
}
18+
const left: Ops<"left"> = {} as any
19+
const right: Ops<"right"> = {} as any
20+
21+
const ok = <F extends Target>(at: Ops<F>) => ({lr: at.lr(at.str, at.num)})
22+
const orphaned = <F extends Target>(at: Ops<F>) => at.dict(ok(at))
23+
24+
const leftOk = ok(left)
25+
const leftOrphaned = orphaned(left)
26+
27+
const rightOk = ok(right)
28+
const rightOrphaned = orphaned(right)
29+
30+
//// [genericFunctionsAndConditionalInference.js]
31+
var left = {};
32+
var right = {};
33+
var ok = function (at) { return ({ lr: at.lr(at.str, at.num) }); };
34+
var orphaned = function (at) { return at.dict(ok(at)); };
35+
var leftOk = ok(left);
36+
var leftOrphaned = orphaned(left);
37+
var rightOk = ok(right);
38+
var rightOrphaned = orphaned(right);
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
=== tests/cases/compiler/genericFunctionsAndConditionalInference.ts ===
2+
interface Targets<A> {
3+
>Targets : Symbol(Targets, Decl(genericFunctionsAndConditionalInference.ts, 0, 0))
4+
>A : Symbol(A, Decl(genericFunctionsAndConditionalInference.ts, 0, 18))
5+
6+
left: A
7+
>left : Symbol(Targets.left, Decl(genericFunctionsAndConditionalInference.ts, 0, 22))
8+
>A : Symbol(A, Decl(genericFunctionsAndConditionalInference.ts, 0, 18))
9+
10+
right: A
11+
>right : Symbol(Targets.right, Decl(genericFunctionsAndConditionalInference.ts, 1, 11))
12+
>A : Symbol(A, Decl(genericFunctionsAndConditionalInference.ts, 0, 18))
13+
}
14+
type Target = keyof Targets<any>
15+
>Target : Symbol(Target, Decl(genericFunctionsAndConditionalInference.ts, 3, 1))
16+
>Targets : Symbol(Targets, Decl(genericFunctionsAndConditionalInference.ts, 0, 0))
17+
18+
type Result<F extends Target, A> = Targets<A>[F]
19+
>Result : Symbol(Result, Decl(genericFunctionsAndConditionalInference.ts, 4, 32))
20+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 5, 12))
21+
>Target : Symbol(Target, Decl(genericFunctionsAndConditionalInference.ts, 3, 1))
22+
>A : Symbol(A, Decl(genericFunctionsAndConditionalInference.ts, 5, 29))
23+
>Targets : Symbol(Targets, Decl(genericFunctionsAndConditionalInference.ts, 0, 0))
24+
>A : Symbol(A, Decl(genericFunctionsAndConditionalInference.ts, 5, 29))
25+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 5, 12))
26+
27+
type LR<F extends Target, L, R> = [F] extends ["left"] ? L : R
28+
>LR : Symbol(LR, Decl(genericFunctionsAndConditionalInference.ts, 5, 48))
29+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 7, 8))
30+
>Target : Symbol(Target, Decl(genericFunctionsAndConditionalInference.ts, 3, 1))
31+
>L : Symbol(L, Decl(genericFunctionsAndConditionalInference.ts, 7, 25))
32+
>R : Symbol(R, Decl(genericFunctionsAndConditionalInference.ts, 7, 28))
33+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 7, 8))
34+
>L : Symbol(L, Decl(genericFunctionsAndConditionalInference.ts, 7, 25))
35+
>R : Symbol(R, Decl(genericFunctionsAndConditionalInference.ts, 7, 28))
36+
37+
interface Ops<F extends Target> {
38+
>Ops : Symbol(Ops, Decl(genericFunctionsAndConditionalInference.ts, 7, 62))
39+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
40+
>Target : Symbol(Target, Decl(genericFunctionsAndConditionalInference.ts, 3, 1))
41+
42+
_f: F
43+
>_f : Symbol(Ops._f, Decl(genericFunctionsAndConditionalInference.ts, 9, 33))
44+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
45+
46+
str: Result<F, string>
47+
>str : Symbol(Ops.str, Decl(genericFunctionsAndConditionalInference.ts, 10, 9))
48+
>Result : Symbol(Result, Decl(genericFunctionsAndConditionalInference.ts, 4, 32))
49+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
50+
51+
num: Result<F, number>
52+
>num : Symbol(Ops.num, Decl(genericFunctionsAndConditionalInference.ts, 11, 26))
53+
>Result : Symbol(Result, Decl(genericFunctionsAndConditionalInference.ts, 4, 32))
54+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
55+
56+
lr<I, O>(a: Result<F, I>, o: Result<F, O>): Result<F, LR<F, I, O>>
57+
>lr : Symbol(Ops.lr, Decl(genericFunctionsAndConditionalInference.ts, 12, 26))
58+
>I : Symbol(I, Decl(genericFunctionsAndConditionalInference.ts, 13, 7))
59+
>O : Symbol(O, Decl(genericFunctionsAndConditionalInference.ts, 13, 9))
60+
>a : Symbol(a, Decl(genericFunctionsAndConditionalInference.ts, 13, 13))
61+
>Result : Symbol(Result, Decl(genericFunctionsAndConditionalInference.ts, 4, 32))
62+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
63+
>I : Symbol(I, Decl(genericFunctionsAndConditionalInference.ts, 13, 7))
64+
>o : Symbol(o, Decl(genericFunctionsAndConditionalInference.ts, 13, 29))
65+
>Result : Symbol(Result, Decl(genericFunctionsAndConditionalInference.ts, 4, 32))
66+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
67+
>O : Symbol(O, Decl(genericFunctionsAndConditionalInference.ts, 13, 9))
68+
>Result : Symbol(Result, Decl(genericFunctionsAndConditionalInference.ts, 4, 32))
69+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
70+
>LR : Symbol(LR, Decl(genericFunctionsAndConditionalInference.ts, 5, 48))
71+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
72+
>I : Symbol(I, Decl(genericFunctionsAndConditionalInference.ts, 13, 7))
73+
>O : Symbol(O, Decl(genericFunctionsAndConditionalInference.ts, 13, 9))
74+
75+
dict: <P>(p: {[k in keyof P]: Result<F, P[k]>}) => Result<F, P>
76+
>dict : Symbol(Ops.dict, Decl(genericFunctionsAndConditionalInference.ts, 13, 70))
77+
>P : Symbol(P, Decl(genericFunctionsAndConditionalInference.ts, 14, 11))
78+
>p : Symbol(p, Decl(genericFunctionsAndConditionalInference.ts, 14, 14))
79+
>k : Symbol(k, Decl(genericFunctionsAndConditionalInference.ts, 14, 19))
80+
>P : Symbol(P, Decl(genericFunctionsAndConditionalInference.ts, 14, 11))
81+
>Result : Symbol(Result, Decl(genericFunctionsAndConditionalInference.ts, 4, 32))
82+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
83+
>P : Symbol(P, Decl(genericFunctionsAndConditionalInference.ts, 14, 11))
84+
>k : Symbol(k, Decl(genericFunctionsAndConditionalInference.ts, 14, 19))
85+
>Result : Symbol(Result, Decl(genericFunctionsAndConditionalInference.ts, 4, 32))
86+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 9, 14))
87+
>P : Symbol(P, Decl(genericFunctionsAndConditionalInference.ts, 14, 11))
88+
}
89+
const left: Ops<"left"> = {} as any
90+
>left : Symbol(left, Decl(genericFunctionsAndConditionalInference.ts, 16, 5))
91+
>Ops : Symbol(Ops, Decl(genericFunctionsAndConditionalInference.ts, 7, 62))
92+
93+
const right: Ops<"right"> = {} as any
94+
>right : Symbol(right, Decl(genericFunctionsAndConditionalInference.ts, 17, 5))
95+
>Ops : Symbol(Ops, Decl(genericFunctionsAndConditionalInference.ts, 7, 62))
96+
97+
const ok = <F extends Target>(at: Ops<F>) => ({lr: at.lr(at.str, at.num)})
98+
>ok : Symbol(ok, Decl(genericFunctionsAndConditionalInference.ts, 19, 5))
99+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 19, 12))
100+
>Target : Symbol(Target, Decl(genericFunctionsAndConditionalInference.ts, 3, 1))
101+
>at : Symbol(at, Decl(genericFunctionsAndConditionalInference.ts, 19, 30))
102+
>Ops : Symbol(Ops, Decl(genericFunctionsAndConditionalInference.ts, 7, 62))
103+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 19, 12))
104+
>lr : Symbol(lr, Decl(genericFunctionsAndConditionalInference.ts, 19, 47))
105+
>at.lr : Symbol(Ops.lr, Decl(genericFunctionsAndConditionalInference.ts, 12, 26))
106+
>at : Symbol(at, Decl(genericFunctionsAndConditionalInference.ts, 19, 30))
107+
>lr : Symbol(Ops.lr, Decl(genericFunctionsAndConditionalInference.ts, 12, 26))
108+
>at.str : Symbol(Ops.str, Decl(genericFunctionsAndConditionalInference.ts, 10, 9))
109+
>at : Symbol(at, Decl(genericFunctionsAndConditionalInference.ts, 19, 30))
110+
>str : Symbol(Ops.str, Decl(genericFunctionsAndConditionalInference.ts, 10, 9))
111+
>at.num : Symbol(Ops.num, Decl(genericFunctionsAndConditionalInference.ts, 11, 26))
112+
>at : Symbol(at, Decl(genericFunctionsAndConditionalInference.ts, 19, 30))
113+
>num : Symbol(Ops.num, Decl(genericFunctionsAndConditionalInference.ts, 11, 26))
114+
115+
const orphaned = <F extends Target>(at: Ops<F>) => at.dict(ok(at))
116+
>orphaned : Symbol(orphaned, Decl(genericFunctionsAndConditionalInference.ts, 20, 5))
117+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 20, 18))
118+
>Target : Symbol(Target, Decl(genericFunctionsAndConditionalInference.ts, 3, 1))
119+
>at : Symbol(at, Decl(genericFunctionsAndConditionalInference.ts, 20, 36))
120+
>Ops : Symbol(Ops, Decl(genericFunctionsAndConditionalInference.ts, 7, 62))
121+
>F : Symbol(F, Decl(genericFunctionsAndConditionalInference.ts, 20, 18))
122+
>at.dict : Symbol(Ops.dict, Decl(genericFunctionsAndConditionalInference.ts, 13, 70))
123+
>at : Symbol(at, Decl(genericFunctionsAndConditionalInference.ts, 20, 36))
124+
>dict : Symbol(Ops.dict, Decl(genericFunctionsAndConditionalInference.ts, 13, 70))
125+
>ok : Symbol(ok, Decl(genericFunctionsAndConditionalInference.ts, 19, 5))
126+
>at : Symbol(at, Decl(genericFunctionsAndConditionalInference.ts, 20, 36))
127+
128+
const leftOk = ok(left)
129+
>leftOk : Symbol(leftOk, Decl(genericFunctionsAndConditionalInference.ts, 22, 5))
130+
>ok : Symbol(ok, Decl(genericFunctionsAndConditionalInference.ts, 19, 5))
131+
>left : Symbol(left, Decl(genericFunctionsAndConditionalInference.ts, 16, 5))
132+
133+
const leftOrphaned = orphaned(left)
134+
>leftOrphaned : Symbol(leftOrphaned, Decl(genericFunctionsAndConditionalInference.ts, 23, 5))
135+
>orphaned : Symbol(orphaned, Decl(genericFunctionsAndConditionalInference.ts, 20, 5))
136+
>left : Symbol(left, Decl(genericFunctionsAndConditionalInference.ts, 16, 5))
137+
138+
const rightOk = ok(right)
139+
>rightOk : Symbol(rightOk, Decl(genericFunctionsAndConditionalInference.ts, 25, 5))
140+
>ok : Symbol(ok, Decl(genericFunctionsAndConditionalInference.ts, 19, 5))
141+
>right : Symbol(right, Decl(genericFunctionsAndConditionalInference.ts, 17, 5))
142+
143+
const rightOrphaned = orphaned(right)
144+
>rightOrphaned : Symbol(rightOrphaned, Decl(genericFunctionsAndConditionalInference.ts, 26, 5))
145+
>orphaned : Symbol(orphaned, Decl(genericFunctionsAndConditionalInference.ts, 20, 5))
146+
>right : Symbol(right, Decl(genericFunctionsAndConditionalInference.ts, 17, 5))
147+
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
=== tests/cases/compiler/genericFunctionsAndConditionalInference.ts ===
2+
interface Targets<A> {
3+
left: A
4+
>left : A
5+
6+
right: A
7+
>right : A
8+
}
9+
type Target = keyof Targets<any>
10+
>Target : keyof Targets<any>
11+
12+
type Result<F extends Target, A> = Targets<A>[F]
13+
>Result : Result<F, A>
14+
15+
type LR<F extends Target, L, R> = [F] extends ["left"] ? L : R
16+
>LR : LR<F, L, R>
17+
18+
interface Ops<F extends Target> {
19+
_f: F
20+
>_f : F
21+
22+
str: Result<F, string>
23+
>str : Result<F, string>
24+
25+
num: Result<F, number>
26+
>num : Result<F, number>
27+
28+
lr<I, O>(a: Result<F, I>, o: Result<F, O>): Result<F, LR<F, I, O>>
29+
>lr : <I, O>(a: Result<F, I>, o: Result<F, O>) => Result<F, LR<F, I, O>>
30+
>a : Result<F, I>
31+
>o : Result<F, O>
32+
33+
dict: <P>(p: {[k in keyof P]: Result<F, P[k]>}) => Result<F, P>
34+
>dict : <P>(p: { [k in keyof P]: Result<F, P[k]>; }) => Result<F, P>
35+
>p : { [k in keyof P]: Result<F, P[k]>; }
36+
}
37+
const left: Ops<"left"> = {} as any
38+
>left : Ops<"left">
39+
>{} as any : any
40+
>{} : {}
41+
42+
const right: Ops<"right"> = {} as any
43+
>right : Ops<"right">
44+
>{} as any : any
45+
>{} : {}
46+
47+
const ok = <F extends Target>(at: Ops<F>) => ({lr: at.lr(at.str, at.num)})
48+
>ok : <F extends keyof Targets<any>>(at: Ops<F>) => { lr: Result<F, LR<F, string, number>>; }
49+
><F extends Target>(at: Ops<F>) => ({lr: at.lr(at.str, at.num)}) : <F extends keyof Targets<any>>(at: Ops<F>) => { lr: Result<F, LR<F, string, number>>; }
50+
>at : Ops<F>
51+
>({lr: at.lr(at.str, at.num)}) : { lr: Result<F, LR<F, string, number>>; }
52+
>{lr: at.lr(at.str, at.num)} : { lr: Result<F, LR<F, string, number>>; }
53+
>lr : Result<F, LR<F, string, number>>
54+
>at.lr(at.str, at.num) : Result<F, LR<F, string, number>>
55+
>at.lr : <I, O>(a: Result<F, I>, o: Result<F, O>) => Result<F, LR<F, I, O>>
56+
>at : Ops<F>
57+
>lr : <I, O>(a: Result<F, I>, o: Result<F, O>) => Result<F, LR<F, I, O>>
58+
>at.str : Result<F, string>
59+
>at : Ops<F>
60+
>str : Result<F, string>
61+
>at.num : Result<F, number>
62+
>at : Ops<F>
63+
>num : Result<F, number>
64+
65+
const orphaned = <F extends Target>(at: Ops<F>) => at.dict(ok(at))
66+
>orphaned : <F extends keyof Targets<any>>(at: Ops<F>) => Result<F, { lr: LR<F, string, number>; }>
67+
><F extends Target>(at: Ops<F>) => at.dict(ok(at)) : <F extends keyof Targets<any>>(at: Ops<F>) => Result<F, { lr: LR<F, string, number>; }>
68+
>at : Ops<F>
69+
>at.dict(ok(at)) : Result<F, { lr: LR<F, string, number>; }>
70+
>at.dict : <P>(p: { [k in keyof P]: Result<F, P[k]>; }) => Result<F, P>
71+
>at : Ops<F>
72+
>dict : <P>(p: { [k in keyof P]: Result<F, P[k]>; }) => Result<F, P>
73+
>ok(at) : { lr: Result<F, LR<F, string, number>>; }
74+
>ok : <F extends keyof Targets<any>>(at: Ops<F>) => { lr: Result<F, LR<F, string, number>>; }
75+
>at : Ops<F>
76+
77+
const leftOk = ok(left)
78+
>leftOk : { lr: string; }
79+
>ok(left) : { lr: string; }
80+
>ok : <F extends keyof Targets<any>>(at: Ops<F>) => { lr: Result<F, LR<F, string, number>>; }
81+
>left : Ops<"left">
82+
83+
const leftOrphaned = orphaned(left)
84+
>leftOrphaned : { lr: string; }
85+
>orphaned(left) : { lr: string; }
86+
>orphaned : <F extends keyof Targets<any>>(at: Ops<F>) => Result<F, { lr: LR<F, string, number>; }>
87+
>left : Ops<"left">
88+
89+
const rightOk = ok(right)
90+
>rightOk : { lr: number; }
91+
>ok(right) : { lr: number; }
92+
>ok : <F extends keyof Targets<any>>(at: Ops<F>) => { lr: Result<F, LR<F, string, number>>; }
93+
>right : Ops<"right">
94+
95+
const rightOrphaned = orphaned(right)
96+
>rightOrphaned : { lr: number; }
97+
>orphaned(right) : { lr: number; }
98+
>orphaned : <F extends keyof Targets<any>>(at: Ops<F>) => Result<F, { lr: LR<F, string, number>; }>
99+
>right : Ops<"right">
100+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
interface Targets<A> {
2+
left: A
3+
right: A
4+
}
5+
type Target = keyof Targets<any>
6+
type Result<F extends Target, A> = Targets<A>[F]
7+
8+
type LR<F extends Target, L, R> = [F] extends ["left"] ? L : R
9+
10+
interface Ops<F extends Target> {
11+
_f: F
12+
str: Result<F, string>
13+
num: Result<F, number>
14+
lr<I, O>(a: Result<F, I>, o: Result<F, O>): Result<F, LR<F, I, O>>
15+
dict: <P>(p: {[k in keyof P]: Result<F, P[k]>}) => Result<F, P>
16+
}
17+
const left: Ops<"left"> = {} as any
18+
const right: Ops<"right"> = {} as any
19+
20+
const ok = <F extends Target>(at: Ops<F>) => ({lr: at.lr(at.str, at.num)})
21+
const orphaned = <F extends Target>(at: Ops<F>) => at.dict(ok(at))
22+
23+
const leftOk = ok(left)
24+
const leftOrphaned = orphaned(left)
25+
26+
const rightOk = ok(right)
27+
const rightOrphaned = orphaned(right)

0 commit comments

Comments
 (0)