diff --git a/src/composeTyping.ts b/src/composeTyping.ts index 08d1bd0..abf537b 100644 --- a/src/composeTyping.ts +++ b/src/composeTyping.ts @@ -9,9 +9,16 @@ type UnwrapPromiseFn = true extends IsAsync ? ( ) => UnwrapPromise> : T; +type GenericGeneric = (x: T) => T; + +// deno-lint-ignore no-explicit-any +type IsGeneric = F extends GenericGeneric ? true + : false; + type SimpleCompose = G extends (...args: infer GArgs) => infer GReturn ? F extends (x: UnwrapPromise) => infer FReturn - ? (...args: GArgs) => UnwrapPromise + ? [true, true] extends [IsGeneric, IsGeneric] ? G + : (...args: GArgs) => UnwrapPromise // todo: does not preserve generics in case of generic identity. : never : never; diff --git a/src/composition.test.ts b/src/composition.test.ts index a6082fa..8225a15 100644 --- a/src/composition.test.ts +++ b/src/composition.test.ts @@ -10,8 +10,8 @@ import { assertEquals } from "std-assert"; import { multiply } from "./math.ts"; import { not } from "./operator.ts"; import { wrapPromise } from "./promise.ts"; -import type { AsyncFunction } from "./typing.ts"; import { sleep } from "./time.ts"; +import type { AsyncFunction } from "./typing.ts"; Deno.test("pipe with async functions", async () => { assertEquals( @@ -105,10 +105,21 @@ const _generics6: number = pipe( (t: T) => t, )(1); +const _generics7: (t: T) => T = pipe( + (t: T) => t, + (t: T) => t, +); + +const _generics8: (t: T) => T = pipe( + // @ts-expect-error no overlap + (t: T) => t, + (t: T) => t, +); + // failing typing tests: // Generics understands contextual extends -// const _5 = number>(f: Fn) => { +// const _generics9 = number>(f: Fn) => { // // @ts-expect-error first function does not match second // pipe((x: number) => x, f); // };