mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Allow infer type variables to have constraints inferred (#32093)
* Allow `infer` type variables to have constraints infered and allow the breakdown of substitutes in simplifiable source inferences * Still skip conditional inference when `extends infer Q` so such a pattern still acts as a constraint size breaker
This commit is contained in:
parent
08e6bc20bb
commit
18cd79e179
@ -12342,6 +12342,13 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function unwrapSubstitution(type: Type): Type {
|
||||
if (type.flags & TypeFlags.Substitution) {
|
||||
return (type as SubstitutionType).substitute;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
|
||||
// the type itself if no transformation is possible. The writing flag indicates that the type is
|
||||
// the target of an assignment.
|
||||
@ -12353,7 +12360,7 @@ namespace ts {
|
||||
type[cache] = circularConstraintType;
|
||||
// We recursively simplify the object type as it may in turn be an indexed access type. For example, with
|
||||
// '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type.
|
||||
const objectType = getSimplifiedType(type.objectType, writing);
|
||||
const objectType = unwrapSubstitution(getSimplifiedType(type.objectType, writing));
|
||||
const indexType = getSimplifiedType(type.indexType, writing);
|
||||
// T[A | B] -> T[A] | T[B] (reading)
|
||||
// T[A | B] -> T[A] & T[B] (writing)
|
||||
@ -12531,7 +12538,11 @@ namespace ts {
|
||||
let combinedMapper: TypeMapper | undefined;
|
||||
if (root.inferTypeParameters) {
|
||||
const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None);
|
||||
if (!checkTypeInstantiable) {
|
||||
// We skip inference of the possible `infer` types unles the `extendsType` _is_ an infer type
|
||||
// if it was, it's trivial to say that extendsType = checkType, however such a pattern is used to
|
||||
// "reset" the type being build up during constraint calculation and avoid making an apparently "infinite" constraint
|
||||
// so in those cases we refain from performing inference and retain the uninfered type parameter
|
||||
if (!checkTypeInstantiable || !some(root.inferTypeParameters, t => t === extendsType)) {
|
||||
// We don't want inferences from constraints as they may cause us to eagerly resolve the
|
||||
// conditional type instead of deferring resolution. Also, we always want strict function
|
||||
// types rules (i.e. proper contravariance) for inferences.
|
||||
@ -17863,6 +17874,12 @@ namespace ts {
|
||||
invokeOnce(source, target, inferFromObjectTypes);
|
||||
}
|
||||
}
|
||||
if (source.flags & TypeFlags.Simplifiable) {
|
||||
const simplified = getSimplifiedType(source, contravariant);
|
||||
if (simplified !== source) {
|
||||
inferFromTypes(simplified, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function inferWithPriority(source: Type, target: Type, newPriority: InferencePriority) {
|
||||
|
||||
123
tests/baselines/reference/ramdaToolsNoInfinite.js
Normal file
123
tests/baselines/reference/ramdaToolsNoInfinite.js
Normal file
@ -0,0 +1,123 @@
|
||||
//// [ramdaToolsNoInfinite.ts]
|
||||
// All the following types are explained here:
|
||||
// https://medium.freecodecamp.org/typescript-curry-ramda-types-f747e99744ab
|
||||
// https://github.com/pirix-gh/medium/blob/master/types-curry-ramda/src/index.ts
|
||||
declare namespace Tools {
|
||||
type Head<T extends any[]> =
|
||||
T extends [any, ...any[]]
|
||||
? T[0]
|
||||
: never;
|
||||
|
||||
type Tail<T extends any[]> =
|
||||
((...t: T) => any) extends ((_: any, ...tail: infer TT) => any)
|
||||
? TT
|
||||
: [];
|
||||
|
||||
type HasTail<T extends any[]> =
|
||||
T extends ([] | [any])
|
||||
? false
|
||||
: true;
|
||||
|
||||
type Last<T extends any[]> = {
|
||||
0: Last<Tail<T>>;
|
||||
1: Head<T>;
|
||||
}[
|
||||
HasTail<T> extends true
|
||||
? 0
|
||||
: 1
|
||||
];
|
||||
|
||||
type Length<T extends any[]> =
|
||||
T['length'];
|
||||
|
||||
type Prepend<E, T extends any[]> =
|
||||
((head: E, ...args: T) => any) extends ((...args: infer U) => any)
|
||||
? U
|
||||
: T;
|
||||
|
||||
type Drop<N extends number, T extends any[], I extends any[] = []> = {
|
||||
0: Drop<N, Tail<T>, Prepend<any, I>>;
|
||||
1: T;
|
||||
}[
|
||||
Length<I> extends N
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Cast<X, Y> = X extends Y ? X : Y;
|
||||
|
||||
type Pos<I extends any[]> =
|
||||
Length<I>;
|
||||
|
||||
type Next<I extends any[]> =
|
||||
Prepend<any, I>;
|
||||
|
||||
type Prev<I extends any[]> =
|
||||
Tail<I>;
|
||||
|
||||
type Iterator<Index extends number = 0, From extends any[] = [], I extends any[] = []> = {
|
||||
0: Iterator<Index, Next<From>, Next<I>>;
|
||||
1: From;
|
||||
}[
|
||||
Pos<I> extends Index
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Reverse<T extends any[], R extends any[] = [], I extends any[] = []> = {
|
||||
0: Reverse<T, Prepend<T[Pos<I>], R>, Next<I>>;
|
||||
1: R;
|
||||
}[
|
||||
Pos<I> extends Length<T>
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Concat<T1 extends any[], T2 extends any[]> =
|
||||
Reverse<Reverse<T1> extends infer R ? Cast<R, any[]> : never, T2>;
|
||||
|
||||
type Append<E, T extends any[]> =
|
||||
Concat<T, [E]>;
|
||||
|
||||
type ValueOfRecord<R> = R extends Record<any, infer T> ? T : never;
|
||||
}
|
||||
|
||||
declare namespace R {
|
||||
export type Placeholder = { __placeholder: void };
|
||||
}
|
||||
|
||||
declare namespace Curry {
|
||||
type GapOf<T1 extends any[], T2 extends any[], TN extends any[], I extends any[]> =
|
||||
T1[Tools.Pos<I>] extends R.Placeholder
|
||||
? Tools.Append<T2[Tools.Pos<I>], TN>
|
||||
: TN;
|
||||
|
||||
interface GapsOfWorker<T1 extends any[], T2 extends any[], TN extends any[] = [], I extends any[] = []> {
|
||||
0: GapsOf<T1, T2, GapOf<T1, T2, TN, I> extends infer G ? Tools.Cast<G, any[]> : never, Tools.Next<I>>;
|
||||
1: Tools.Concat<TN, Tools.Drop<Tools.Pos<I>, T2> extends infer D ? Tools.Cast<D, any[]> : never>;
|
||||
}
|
||||
type GapsOf<T1 extends any[], T2 extends any[], TN extends any[] = [], I extends any[] = []> = GapsOfWorker<T1, T2, TN, I>[
|
||||
Tools.Pos<I> extends Tools.Length<T1>
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type PartialGaps<T extends any[]> = {
|
||||
[K in keyof T]?: T[K] | R.Placeholder
|
||||
};
|
||||
|
||||
type CleanedGaps<T extends any[]> = {
|
||||
[K in keyof T]: NonNullable<T[K]>
|
||||
};
|
||||
|
||||
type Gaps<T extends any[]> = CleanedGaps<PartialGaps<T>>;
|
||||
|
||||
type Curry<F extends ((...args: any) => any)> =
|
||||
<T extends any[]>(...args: Tools.Cast<Tools.Cast<T, Gaps<Parameters<F>>>, any[]>) =>
|
||||
GapsOf<T, Parameters<F>> extends [any, ...any[]]
|
||||
? Curry<(...args: GapsOf<T, Parameters<F>> extends infer G ? Tools.Cast<G, any[]> : never) => ReturnType<F>>
|
||||
: ReturnType<F>;
|
||||
}
|
||||
|
||||
|
||||
//// [ramdaToolsNoInfinite.js]
|
||||
431
tests/baselines/reference/ramdaToolsNoInfinite.symbols
Normal file
431
tests/baselines/reference/ramdaToolsNoInfinite.symbols
Normal file
@ -0,0 +1,431 @@
|
||||
=== tests/cases/compiler/ramdaToolsNoInfinite.ts ===
|
||||
// All the following types are explained here:
|
||||
// https://medium.freecodecamp.org/typescript-curry-ramda-types-f747e99744ab
|
||||
// https://github.com/pirix-gh/medium/blob/master/types-curry-ramda/src/index.ts
|
||||
declare namespace Tools {
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
|
||||
type Head<T extends any[]> =
|
||||
>Head : Symbol(Head, Decl(ramdaToolsNoInfinite.ts, 3, 25))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 4, 14))
|
||||
|
||||
T extends [any, ...any[]]
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 4, 14))
|
||||
|
||||
? T[0]
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 4, 14))
|
||||
|
||||
: never;
|
||||
|
||||
type Tail<T extends any[]> =
|
||||
>Tail : Symbol(Tail, Decl(ramdaToolsNoInfinite.ts, 7, 16))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 9, 14))
|
||||
|
||||
((...t: T) => any) extends ((_: any, ...tail: infer TT) => any)
|
||||
>t : Symbol(t, Decl(ramdaToolsNoInfinite.ts, 10, 10))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 9, 14))
|
||||
>_ : Symbol(_, Decl(ramdaToolsNoInfinite.ts, 10, 37))
|
||||
>tail : Symbol(tail, Decl(ramdaToolsNoInfinite.ts, 10, 44))
|
||||
>TT : Symbol(TT, Decl(ramdaToolsNoInfinite.ts, 10, 59))
|
||||
|
||||
? TT
|
||||
>TT : Symbol(TT, Decl(ramdaToolsNoInfinite.ts, 10, 59))
|
||||
|
||||
: [];
|
||||
|
||||
type HasTail<T extends any[]> =
|
||||
>HasTail : Symbol(HasTail, Decl(ramdaToolsNoInfinite.ts, 12, 13))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 14, 17))
|
||||
|
||||
T extends ([] | [any])
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 14, 17))
|
||||
|
||||
? false
|
||||
: true;
|
||||
|
||||
type Last<T extends any[]> = {
|
||||
>Last : Symbol(Last, Decl(ramdaToolsNoInfinite.ts, 17, 15))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 19, 14))
|
||||
|
||||
0: Last<Tail<T>>;
|
||||
>0 : Symbol(0, Decl(ramdaToolsNoInfinite.ts, 19, 34))
|
||||
>Last : Symbol(Last, Decl(ramdaToolsNoInfinite.ts, 17, 15))
|
||||
>Tail : Symbol(Tail, Decl(ramdaToolsNoInfinite.ts, 7, 16))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 19, 14))
|
||||
|
||||
1: Head<T>;
|
||||
>1 : Symbol(1, Decl(ramdaToolsNoInfinite.ts, 20, 25))
|
||||
>Head : Symbol(Head, Decl(ramdaToolsNoInfinite.ts, 3, 25))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 19, 14))
|
||||
|
||||
}[
|
||||
HasTail<T> extends true
|
||||
>HasTail : Symbol(HasTail, Decl(ramdaToolsNoInfinite.ts, 12, 13))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 19, 14))
|
||||
|
||||
? 0
|
||||
: 1
|
||||
];
|
||||
|
||||
type Length<T extends any[]> =
|
||||
>Length : Symbol(Length, Decl(ramdaToolsNoInfinite.ts, 26, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 28, 16))
|
||||
|
||||
T['length'];
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 28, 16))
|
||||
|
||||
type Prepend<E, T extends any[]> =
|
||||
>Prepend : Symbol(Prepend, Decl(ramdaToolsNoInfinite.ts, 29, 20))
|
||||
>E : Symbol(E, Decl(ramdaToolsNoInfinite.ts, 31, 17))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 31, 19))
|
||||
|
||||
((head: E, ...args: T) => any) extends ((...args: infer U) => any)
|
||||
>head : Symbol(head, Decl(ramdaToolsNoInfinite.ts, 32, 10))
|
||||
>E : Symbol(E, Decl(ramdaToolsNoInfinite.ts, 31, 17))
|
||||
>args : Symbol(args, Decl(ramdaToolsNoInfinite.ts, 32, 18))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 31, 19))
|
||||
>args : Symbol(args, Decl(ramdaToolsNoInfinite.ts, 32, 49))
|
||||
>U : Symbol(U, Decl(ramdaToolsNoInfinite.ts, 32, 63))
|
||||
|
||||
? U
|
||||
>U : Symbol(U, Decl(ramdaToolsNoInfinite.ts, 32, 63))
|
||||
|
||||
: T;
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 31, 19))
|
||||
|
||||
type Drop<N extends number, T extends any[], I extends any[] = []> = {
|
||||
>Drop : Symbol(Drop, Decl(ramdaToolsNoInfinite.ts, 34, 12))
|
||||
>N : Symbol(N, Decl(ramdaToolsNoInfinite.ts, 36, 14))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 36, 31))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 36, 48))
|
||||
|
||||
0: Drop<N, Tail<T>, Prepend<any, I>>;
|
||||
>0 : Symbol(0, Decl(ramdaToolsNoInfinite.ts, 36, 74))
|
||||
>Drop : Symbol(Drop, Decl(ramdaToolsNoInfinite.ts, 34, 12))
|
||||
>N : Symbol(N, Decl(ramdaToolsNoInfinite.ts, 36, 14))
|
||||
>Tail : Symbol(Tail, Decl(ramdaToolsNoInfinite.ts, 7, 16))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 36, 31))
|
||||
>Prepend : Symbol(Prepend, Decl(ramdaToolsNoInfinite.ts, 29, 20))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 36, 48))
|
||||
|
||||
1: T;
|
||||
>1 : Symbol(1, Decl(ramdaToolsNoInfinite.ts, 37, 45))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 36, 31))
|
||||
|
||||
}[
|
||||
Length<I> extends N
|
||||
>Length : Symbol(Length, Decl(ramdaToolsNoInfinite.ts, 26, 6))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 36, 48))
|
||||
>N : Symbol(N, Decl(ramdaToolsNoInfinite.ts, 36, 14))
|
||||
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Cast<X, Y> = X extends Y ? X : Y;
|
||||
>Cast : Symbol(Cast, Decl(ramdaToolsNoInfinite.ts, 43, 6))
|
||||
>X : Symbol(X, Decl(ramdaToolsNoInfinite.ts, 45, 14))
|
||||
>Y : Symbol(Y, Decl(ramdaToolsNoInfinite.ts, 45, 16))
|
||||
>X : Symbol(X, Decl(ramdaToolsNoInfinite.ts, 45, 14))
|
||||
>Y : Symbol(Y, Decl(ramdaToolsNoInfinite.ts, 45, 16))
|
||||
>X : Symbol(X, Decl(ramdaToolsNoInfinite.ts, 45, 14))
|
||||
>Y : Symbol(Y, Decl(ramdaToolsNoInfinite.ts, 45, 16))
|
||||
|
||||
type Pos<I extends any[]> =
|
||||
>Pos : Symbol(Pos, Decl(ramdaToolsNoInfinite.ts, 45, 42))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 47, 13))
|
||||
|
||||
Length<I>;
|
||||
>Length : Symbol(Length, Decl(ramdaToolsNoInfinite.ts, 26, 6))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 47, 13))
|
||||
|
||||
type Next<I extends any[]> =
|
||||
>Next : Symbol(Next, Decl(ramdaToolsNoInfinite.ts, 48, 18))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 50, 14))
|
||||
|
||||
Prepend<any, I>;
|
||||
>Prepend : Symbol(Prepend, Decl(ramdaToolsNoInfinite.ts, 29, 20))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 50, 14))
|
||||
|
||||
type Prev<I extends any[]> =
|
||||
>Prev : Symbol(Prev, Decl(ramdaToolsNoInfinite.ts, 51, 24))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 53, 14))
|
||||
|
||||
Tail<I>;
|
||||
>Tail : Symbol(Tail, Decl(ramdaToolsNoInfinite.ts, 7, 16))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 53, 14))
|
||||
|
||||
type Iterator<Index extends number = 0, From extends any[] = [], I extends any[] = []> = {
|
||||
>Iterator : Symbol(Iterator, Decl(ramdaToolsNoInfinite.ts, 54, 16))
|
||||
>Index : Symbol(Index, Decl(ramdaToolsNoInfinite.ts, 56, 18))
|
||||
>From : Symbol(From, Decl(ramdaToolsNoInfinite.ts, 56, 43))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 56, 68))
|
||||
|
||||
0: Iterator<Index, Next<From>, Next<I>>;
|
||||
>0 : Symbol(0, Decl(ramdaToolsNoInfinite.ts, 56, 94))
|
||||
>Iterator : Symbol(Iterator, Decl(ramdaToolsNoInfinite.ts, 54, 16))
|
||||
>Index : Symbol(Index, Decl(ramdaToolsNoInfinite.ts, 56, 18))
|
||||
>Next : Symbol(Next, Decl(ramdaToolsNoInfinite.ts, 48, 18))
|
||||
>From : Symbol(From, Decl(ramdaToolsNoInfinite.ts, 56, 43))
|
||||
>Next : Symbol(Next, Decl(ramdaToolsNoInfinite.ts, 48, 18))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 56, 68))
|
||||
|
||||
1: From;
|
||||
>1 : Symbol(1, Decl(ramdaToolsNoInfinite.ts, 57, 48))
|
||||
>From : Symbol(From, Decl(ramdaToolsNoInfinite.ts, 56, 43))
|
||||
|
||||
}[
|
||||
Pos<I> extends Index
|
||||
>Pos : Symbol(Pos, Decl(ramdaToolsNoInfinite.ts, 45, 42))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 56, 68))
|
||||
>Index : Symbol(Index, Decl(ramdaToolsNoInfinite.ts, 56, 18))
|
||||
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Reverse<T extends any[], R extends any[] = [], I extends any[] = []> = {
|
||||
>Reverse : Symbol(Reverse, Decl(ramdaToolsNoInfinite.ts, 63, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 65, 17))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 65, 33))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 65, 55))
|
||||
|
||||
0: Reverse<T, Prepend<T[Pos<I>], R>, Next<I>>;
|
||||
>0 : Symbol(0, Decl(ramdaToolsNoInfinite.ts, 65, 81))
|
||||
>Reverse : Symbol(Reverse, Decl(ramdaToolsNoInfinite.ts, 63, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 65, 17))
|
||||
>Prepend : Symbol(Prepend, Decl(ramdaToolsNoInfinite.ts, 29, 20))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 65, 17))
|
||||
>Pos : Symbol(Pos, Decl(ramdaToolsNoInfinite.ts, 45, 42))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 65, 55))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 65, 33))
|
||||
>Next : Symbol(Next, Decl(ramdaToolsNoInfinite.ts, 48, 18))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 65, 55))
|
||||
|
||||
1: R;
|
||||
>1 : Symbol(1, Decl(ramdaToolsNoInfinite.ts, 66, 54))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 65, 33))
|
||||
|
||||
}[
|
||||
Pos<I> extends Length<T>
|
||||
>Pos : Symbol(Pos, Decl(ramdaToolsNoInfinite.ts, 45, 42))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 65, 55))
|
||||
>Length : Symbol(Length, Decl(ramdaToolsNoInfinite.ts, 26, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 65, 17))
|
||||
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Concat<T1 extends any[], T2 extends any[]> =
|
||||
>Concat : Symbol(Concat, Decl(ramdaToolsNoInfinite.ts, 72, 6))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 74, 16))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 74, 33))
|
||||
|
||||
Reverse<Reverse<T1> extends infer R ? Cast<R, any[]> : never, T2>;
|
||||
>Reverse : Symbol(Reverse, Decl(ramdaToolsNoInfinite.ts, 63, 6))
|
||||
>Reverse : Symbol(Reverse, Decl(ramdaToolsNoInfinite.ts, 63, 6))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 74, 16))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 75, 41))
|
||||
>Cast : Symbol(Cast, Decl(ramdaToolsNoInfinite.ts, 43, 6))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 75, 41))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 74, 33))
|
||||
|
||||
type Append<E, T extends any[]> =
|
||||
>Append : Symbol(Append, Decl(ramdaToolsNoInfinite.ts, 75, 74))
|
||||
>E : Symbol(E, Decl(ramdaToolsNoInfinite.ts, 77, 16))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 77, 18))
|
||||
|
||||
Concat<T, [E]>;
|
||||
>Concat : Symbol(Concat, Decl(ramdaToolsNoInfinite.ts, 72, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 77, 18))
|
||||
>E : Symbol(E, Decl(ramdaToolsNoInfinite.ts, 77, 16))
|
||||
|
||||
type ValueOfRecord<R> = R extends Record<any, infer T> ? T : never;
|
||||
>ValueOfRecord : Symbol(ValueOfRecord, Decl(ramdaToolsNoInfinite.ts, 78, 23))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 80, 23))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 80, 23))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 80, 55))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 80, 55))
|
||||
}
|
||||
|
||||
declare namespace R {
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 81, 1))
|
||||
|
||||
export type Placeholder = { __placeholder: void };
|
||||
>Placeholder : Symbol(Placeholder, Decl(ramdaToolsNoInfinite.ts, 83, 21))
|
||||
>__placeholder : Symbol(__placeholder, Decl(ramdaToolsNoInfinite.ts, 84, 31))
|
||||
}
|
||||
|
||||
declare namespace Curry {
|
||||
>Curry : Symbol(Curry, Decl(ramdaToolsNoInfinite.ts, 85, 1))
|
||||
|
||||
type GapOf<T1 extends any[], T2 extends any[], TN extends any[], I extends any[]> =
|
||||
>GapOf : Symbol(GapOf, Decl(ramdaToolsNoInfinite.ts, 87, 25))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 88, 15))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 88, 32))
|
||||
>TN : Symbol(TN, Decl(ramdaToolsNoInfinite.ts, 88, 50))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 88, 68))
|
||||
|
||||
T1[Tools.Pos<I>] extends R.Placeholder
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 88, 15))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Pos : Symbol(Tools.Pos, Decl(ramdaToolsNoInfinite.ts, 45, 42))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 88, 68))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 81, 1))
|
||||
>Placeholder : Symbol(R.Placeholder, Decl(ramdaToolsNoInfinite.ts, 83, 21))
|
||||
|
||||
? Tools.Append<T2[Tools.Pos<I>], TN>
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Append : Symbol(Tools.Append, Decl(ramdaToolsNoInfinite.ts, 75, 74))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 88, 32))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Pos : Symbol(Tools.Pos, Decl(ramdaToolsNoInfinite.ts, 45, 42))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 88, 68))
|
||||
>TN : Symbol(TN, Decl(ramdaToolsNoInfinite.ts, 88, 50))
|
||||
|
||||
: TN;
|
||||
>TN : Symbol(TN, Decl(ramdaToolsNoInfinite.ts, 88, 50))
|
||||
|
||||
interface GapsOfWorker<T1 extends any[], T2 extends any[], TN extends any[] = [], I extends any[] = []> {
|
||||
>GapsOfWorker : Symbol(GapsOfWorker, Decl(ramdaToolsNoInfinite.ts, 91, 13))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 93, 27))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 93, 44))
|
||||
>TN : Symbol(TN, Decl(ramdaToolsNoInfinite.ts, 93, 62))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 93, 85))
|
||||
|
||||
0: GapsOf<T1, T2, GapOf<T1, T2, TN, I> extends infer G ? Tools.Cast<G, any[]> : never, Tools.Next<I>>;
|
||||
>0 : Symbol(GapsOfWorker[0], Decl(ramdaToolsNoInfinite.ts, 93, 109))
|
||||
>GapsOf : Symbol(GapsOf, Decl(ramdaToolsNoInfinite.ts, 96, 5))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 93, 27))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 93, 44))
|
||||
>GapOf : Symbol(GapOf, Decl(ramdaToolsNoInfinite.ts, 87, 25))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 93, 27))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 93, 44))
|
||||
>TN : Symbol(TN, Decl(ramdaToolsNoInfinite.ts, 93, 62))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 93, 85))
|
||||
>G : Symbol(G, Decl(ramdaToolsNoInfinite.ts, 94, 60))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Cast : Symbol(Tools.Cast, Decl(ramdaToolsNoInfinite.ts, 43, 6))
|
||||
>G : Symbol(G, Decl(ramdaToolsNoInfinite.ts, 94, 60))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Next : Symbol(Tools.Next, Decl(ramdaToolsNoInfinite.ts, 48, 18))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 93, 85))
|
||||
|
||||
1: Tools.Concat<TN, Tools.Drop<Tools.Pos<I>, T2> extends infer D ? Tools.Cast<D, any[]> : never>;
|
||||
>1 : Symbol(GapsOfWorker[1], Decl(ramdaToolsNoInfinite.ts, 94, 110))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Concat : Symbol(Tools.Concat, Decl(ramdaToolsNoInfinite.ts, 72, 6))
|
||||
>TN : Symbol(TN, Decl(ramdaToolsNoInfinite.ts, 93, 62))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Drop : Symbol(Tools.Drop, Decl(ramdaToolsNoInfinite.ts, 34, 12))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Pos : Symbol(Tools.Pos, Decl(ramdaToolsNoInfinite.ts, 45, 42))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 93, 85))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 93, 44))
|
||||
>D : Symbol(D, Decl(ramdaToolsNoInfinite.ts, 95, 70))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Cast : Symbol(Tools.Cast, Decl(ramdaToolsNoInfinite.ts, 43, 6))
|
||||
>D : Symbol(D, Decl(ramdaToolsNoInfinite.ts, 95, 70))
|
||||
}
|
||||
type GapsOf<T1 extends any[], T2 extends any[], TN extends any[] = [], I extends any[] = []> = GapsOfWorker<T1, T2, TN, I>[
|
||||
>GapsOf : Symbol(GapsOf, Decl(ramdaToolsNoInfinite.ts, 96, 5))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 97, 16))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 97, 33))
|
||||
>TN : Symbol(TN, Decl(ramdaToolsNoInfinite.ts, 97, 51))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 97, 74))
|
||||
>GapsOfWorker : Symbol(GapsOfWorker, Decl(ramdaToolsNoInfinite.ts, 91, 13))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 97, 16))
|
||||
>T2 : Symbol(T2, Decl(ramdaToolsNoInfinite.ts, 97, 33))
|
||||
>TN : Symbol(TN, Decl(ramdaToolsNoInfinite.ts, 97, 51))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 97, 74))
|
||||
|
||||
Tools.Pos<I> extends Tools.Length<T1>
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Pos : Symbol(Tools.Pos, Decl(ramdaToolsNoInfinite.ts, 45, 42))
|
||||
>I : Symbol(I, Decl(ramdaToolsNoInfinite.ts, 97, 74))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Length : Symbol(Tools.Length, Decl(ramdaToolsNoInfinite.ts, 26, 6))
|
||||
>T1 : Symbol(T1, Decl(ramdaToolsNoInfinite.ts, 97, 16))
|
||||
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type PartialGaps<T extends any[]> = {
|
||||
>PartialGaps : Symbol(PartialGaps, Decl(ramdaToolsNoInfinite.ts, 101, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 103, 21))
|
||||
|
||||
[K in keyof T]?: T[K] | R.Placeholder
|
||||
>K : Symbol(K, Decl(ramdaToolsNoInfinite.ts, 104, 9))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 103, 21))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 103, 21))
|
||||
>K : Symbol(K, Decl(ramdaToolsNoInfinite.ts, 104, 9))
|
||||
>R : Symbol(R, Decl(ramdaToolsNoInfinite.ts, 81, 1))
|
||||
>Placeholder : Symbol(R.Placeholder, Decl(ramdaToolsNoInfinite.ts, 83, 21))
|
||||
|
||||
};
|
||||
|
||||
type CleanedGaps<T extends any[]> = {
|
||||
>CleanedGaps : Symbol(CleanedGaps, Decl(ramdaToolsNoInfinite.ts, 105, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 107, 21))
|
||||
|
||||
[K in keyof T]: NonNullable<T[K]>
|
||||
>K : Symbol(K, Decl(ramdaToolsNoInfinite.ts, 108, 9))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 107, 21))
|
||||
>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 107, 21))
|
||||
>K : Symbol(K, Decl(ramdaToolsNoInfinite.ts, 108, 9))
|
||||
|
||||
};
|
||||
|
||||
type Gaps<T extends any[]> = CleanedGaps<PartialGaps<T>>;
|
||||
>Gaps : Symbol(Gaps, Decl(ramdaToolsNoInfinite.ts, 109, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 111, 14))
|
||||
>CleanedGaps : Symbol(CleanedGaps, Decl(ramdaToolsNoInfinite.ts, 105, 6))
|
||||
>PartialGaps : Symbol(PartialGaps, Decl(ramdaToolsNoInfinite.ts, 101, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 111, 14))
|
||||
|
||||
type Curry<F extends ((...args: any) => any)> =
|
||||
>Curry : Symbol(Curry, Decl(ramdaToolsNoInfinite.ts, 111, 61))
|
||||
>F : Symbol(F, Decl(ramdaToolsNoInfinite.ts, 113, 15))
|
||||
>args : Symbol(args, Decl(ramdaToolsNoInfinite.ts, 113, 27))
|
||||
|
||||
<T extends any[]>(...args: Tools.Cast<Tools.Cast<T, Gaps<Parameters<F>>>, any[]>) =>
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 114, 9))
|
||||
>args : Symbol(args, Decl(ramdaToolsNoInfinite.ts, 114, 26))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Cast : Symbol(Tools.Cast, Decl(ramdaToolsNoInfinite.ts, 43, 6))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Cast : Symbol(Tools.Cast, Decl(ramdaToolsNoInfinite.ts, 43, 6))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 114, 9))
|
||||
>Gaps : Symbol(Gaps, Decl(ramdaToolsNoInfinite.ts, 109, 6))
|
||||
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
|
||||
>F : Symbol(F, Decl(ramdaToolsNoInfinite.ts, 113, 15))
|
||||
|
||||
GapsOf<T, Parameters<F>> extends [any, ...any[]]
|
||||
>GapsOf : Symbol(GapsOf, Decl(ramdaToolsNoInfinite.ts, 96, 5))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 114, 9))
|
||||
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
|
||||
>F : Symbol(F, Decl(ramdaToolsNoInfinite.ts, 113, 15))
|
||||
|
||||
? Curry<(...args: GapsOf<T, Parameters<F>> extends infer G ? Tools.Cast<G, any[]> : never) => ReturnType<F>>
|
||||
>Curry : Symbol(Curry, Decl(ramdaToolsNoInfinite.ts, 111, 61))
|
||||
>args : Symbol(args, Decl(ramdaToolsNoInfinite.ts, 116, 21))
|
||||
>GapsOf : Symbol(GapsOf, Decl(ramdaToolsNoInfinite.ts, 96, 5))
|
||||
>T : Symbol(T, Decl(ramdaToolsNoInfinite.ts, 114, 9))
|
||||
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
|
||||
>F : Symbol(F, Decl(ramdaToolsNoInfinite.ts, 113, 15))
|
||||
>G : Symbol(G, Decl(ramdaToolsNoInfinite.ts, 116, 68))
|
||||
>Tools : Symbol(Tools, Decl(ramdaToolsNoInfinite.ts, 0, 0))
|
||||
>Cast : Symbol(Tools.Cast, Decl(ramdaToolsNoInfinite.ts, 43, 6))
|
||||
>G : Symbol(G, Decl(ramdaToolsNoInfinite.ts, 116, 68))
|
||||
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
|
||||
>F : Symbol(F, Decl(ramdaToolsNoInfinite.ts, 113, 15))
|
||||
|
||||
: ReturnType<F>;
|
||||
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
|
||||
>F : Symbol(F, Decl(ramdaToolsNoInfinite.ts, 113, 15))
|
||||
}
|
||||
|
||||
221
tests/baselines/reference/ramdaToolsNoInfinite.types
Normal file
221
tests/baselines/reference/ramdaToolsNoInfinite.types
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@
|
||||
//// [substituteReturnTypeSatisfiesConstraint.ts]
|
||||
type M = { p: string };
|
||||
type O = { m: () => M };
|
||||
type X<T extends M> = T;
|
||||
type FFG<T> = T extends O ? X<ReturnType<T['m']>> : never; // error!
|
||||
|
||||
|
||||
//// [substituteReturnTypeSatisfiesConstraint.js]
|
||||
@ -0,0 +1,25 @@
|
||||
=== tests/cases/compiler/substituteReturnTypeSatisfiesConstraint.ts ===
|
||||
type M = { p: string };
|
||||
>M : Symbol(M, Decl(substituteReturnTypeSatisfiesConstraint.ts, 0, 0))
|
||||
>p : Symbol(p, Decl(substituteReturnTypeSatisfiesConstraint.ts, 0, 10))
|
||||
|
||||
type O = { m: () => M };
|
||||
>O : Symbol(O, Decl(substituteReturnTypeSatisfiesConstraint.ts, 0, 23))
|
||||
>m : Symbol(m, Decl(substituteReturnTypeSatisfiesConstraint.ts, 1, 10))
|
||||
>M : Symbol(M, Decl(substituteReturnTypeSatisfiesConstraint.ts, 0, 0))
|
||||
|
||||
type X<T extends M> = T;
|
||||
>X : Symbol(X, Decl(substituteReturnTypeSatisfiesConstraint.ts, 1, 24))
|
||||
>T : Symbol(T, Decl(substituteReturnTypeSatisfiesConstraint.ts, 2, 7))
|
||||
>M : Symbol(M, Decl(substituteReturnTypeSatisfiesConstraint.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(substituteReturnTypeSatisfiesConstraint.ts, 2, 7))
|
||||
|
||||
type FFG<T> = T extends O ? X<ReturnType<T['m']>> : never; // error!
|
||||
>FFG : Symbol(FFG, Decl(substituteReturnTypeSatisfiesConstraint.ts, 2, 24))
|
||||
>T : Symbol(T, Decl(substituteReturnTypeSatisfiesConstraint.ts, 3, 9))
|
||||
>T : Symbol(T, Decl(substituteReturnTypeSatisfiesConstraint.ts, 3, 9))
|
||||
>O : Symbol(O, Decl(substituteReturnTypeSatisfiesConstraint.ts, 0, 23))
|
||||
>X : Symbol(X, Decl(substituteReturnTypeSatisfiesConstraint.ts, 1, 24))
|
||||
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(substituteReturnTypeSatisfiesConstraint.ts, 3, 9))
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
=== tests/cases/compiler/substituteReturnTypeSatisfiesConstraint.ts ===
|
||||
type M = { p: string };
|
||||
>M : M
|
||||
>p : string
|
||||
|
||||
type O = { m: () => M };
|
||||
>O : O
|
||||
>m : () => M
|
||||
|
||||
type X<T extends M> = T;
|
||||
>X : T
|
||||
|
||||
type FFG<T> = T extends O ? X<ReturnType<T['m']>> : never; // error!
|
||||
>FFG : FFG<T>
|
||||
|
||||
120
tests/cases/compiler/ramdaToolsNoInfinite.ts
Normal file
120
tests/cases/compiler/ramdaToolsNoInfinite.ts
Normal file
@ -0,0 +1,120 @@
|
||||
|
||||
// All the following types are explained here:
|
||||
// https://medium.freecodecamp.org/typescript-curry-ramda-types-f747e99744ab
|
||||
// https://github.com/pirix-gh/medium/blob/master/types-curry-ramda/src/index.ts
|
||||
declare namespace Tools {
|
||||
type Head<T extends any[]> =
|
||||
T extends [any, ...any[]]
|
||||
? T[0]
|
||||
: never;
|
||||
|
||||
type Tail<T extends any[]> =
|
||||
((...t: T) => any) extends ((_: any, ...tail: infer TT) => any)
|
||||
? TT
|
||||
: [];
|
||||
|
||||
type HasTail<T extends any[]> =
|
||||
T extends ([] | [any])
|
||||
? false
|
||||
: true;
|
||||
|
||||
type Last<T extends any[]> = {
|
||||
0: Last<Tail<T>>;
|
||||
1: Head<T>;
|
||||
}[
|
||||
HasTail<T> extends true
|
||||
? 0
|
||||
: 1
|
||||
];
|
||||
|
||||
type Length<T extends any[]> =
|
||||
T['length'];
|
||||
|
||||
type Prepend<E, T extends any[]> =
|
||||
((head: E, ...args: T) => any) extends ((...args: infer U) => any)
|
||||
? U
|
||||
: T;
|
||||
|
||||
type Drop<N extends number, T extends any[], I extends any[] = []> = {
|
||||
0: Drop<N, Tail<T>, Prepend<any, I>>;
|
||||
1: T;
|
||||
}[
|
||||
Length<I> extends N
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Cast<X, Y> = X extends Y ? X : Y;
|
||||
|
||||
type Pos<I extends any[]> =
|
||||
Length<I>;
|
||||
|
||||
type Next<I extends any[]> =
|
||||
Prepend<any, I>;
|
||||
|
||||
type Prev<I extends any[]> =
|
||||
Tail<I>;
|
||||
|
||||
type Iterator<Index extends number = 0, From extends any[] = [], I extends any[] = []> = {
|
||||
0: Iterator<Index, Next<From>, Next<I>>;
|
||||
1: From;
|
||||
}[
|
||||
Pos<I> extends Index
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Reverse<T extends any[], R extends any[] = [], I extends any[] = []> = {
|
||||
0: Reverse<T, Prepend<T[Pos<I>], R>, Next<I>>;
|
||||
1: R;
|
||||
}[
|
||||
Pos<I> extends Length<T>
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type Concat<T1 extends any[], T2 extends any[]> =
|
||||
Reverse<Reverse<T1> extends infer R ? Cast<R, any[]> : never, T2>;
|
||||
|
||||
type Append<E, T extends any[]> =
|
||||
Concat<T, [E]>;
|
||||
|
||||
type ValueOfRecord<R> = R extends Record<any, infer T> ? T : never;
|
||||
}
|
||||
|
||||
declare namespace R {
|
||||
export type Placeholder = { __placeholder: void };
|
||||
}
|
||||
|
||||
declare namespace Curry {
|
||||
type GapOf<T1 extends any[], T2 extends any[], TN extends any[], I extends any[]> =
|
||||
T1[Tools.Pos<I>] extends R.Placeholder
|
||||
? Tools.Append<T2[Tools.Pos<I>], TN>
|
||||
: TN;
|
||||
|
||||
interface GapsOfWorker<T1 extends any[], T2 extends any[], TN extends any[] = [], I extends any[] = []> {
|
||||
0: GapsOf<T1, T2, GapOf<T1, T2, TN, I> extends infer G ? Tools.Cast<G, any[]> : never, Tools.Next<I>>;
|
||||
1: Tools.Concat<TN, Tools.Drop<Tools.Pos<I>, T2> extends infer D ? Tools.Cast<D, any[]> : never>;
|
||||
}
|
||||
type GapsOf<T1 extends any[], T2 extends any[], TN extends any[] = [], I extends any[] = []> = GapsOfWorker<T1, T2, TN, I>[
|
||||
Tools.Pos<I> extends Tools.Length<T1>
|
||||
? 1
|
||||
: 0
|
||||
];
|
||||
|
||||
type PartialGaps<T extends any[]> = {
|
||||
[K in keyof T]?: T[K] | R.Placeholder
|
||||
};
|
||||
|
||||
type CleanedGaps<T extends any[]> = {
|
||||
[K in keyof T]: NonNullable<T[K]>
|
||||
};
|
||||
|
||||
type Gaps<T extends any[]> = CleanedGaps<PartialGaps<T>>;
|
||||
|
||||
type Curry<F extends ((...args: any) => any)> =
|
||||
<T extends any[]>(...args: Tools.Cast<Tools.Cast<T, Gaps<Parameters<F>>>, any[]>) =>
|
||||
GapsOf<T, Parameters<F>> extends [any, ...any[]]
|
||||
? Curry<(...args: GapsOf<T, Parameters<F>> extends infer G ? Tools.Cast<G, any[]> : never) => ReturnType<F>>
|
||||
: ReturnType<F>;
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
type M = { p: string };
|
||||
type O = { m: () => M };
|
||||
type X<T extends M> = T;
|
||||
type FFG<T> = T extends O ? X<ReturnType<T['m']>> : never; // error!
|
||||
Loading…
x
Reference in New Issue
Block a user