import {Dependency, ImpType, ImpReturns} from "../core/Dispatcher"; declare module "./type" { interface GenericReturn { // Jos: not sure how to define this or why it is needed // square: Signature // square: ConservativeUnary // square: Params extends [infer R] // ? R extends number ? UnderlyingReal : never // : never // The type of `square` in this interface, instantiated with the type // Params of a parameter list, needs to be the return type of the // operation `square` on those parameters. In other words, `square` gives // a type transformer from the tuple type of its parameters to its return // type. // That's how Dispatcher knows what the return type will be in // `Dependency<'square', [bigint]>`, for example: it instantiates // GenericReturn with Params equal to [bigint] and then grabs the // type of the `square` property. Hence we write: square: Params extends [infer T] // square only takes 1 arbitrary parameter ? ImpReturns<'multiply', [T, T]> // and returns whatever multiply does : never; // otherwise if not a single argument, this implementation // doesn't handle it // If square had more than one implementation in this collection, we could // either add more conditional clauses to the above type transformer // as I did in Complex/type.ts for `complex`, or we could have two // different keys that both start with `square_` and Dispatcher will // check both (as I have now done in comments in Complex/type.ts and // verified that also works). } } export const square = (dep: Dependency<'multiply', [T, T]>): ImpType<'square', [T]> => z => dep.multiply(z, z)