40 lines
1.7 KiB
TypeScript
40 lines
1.7 KiB
TypeScript
import {Dependency, ImpType, ImpReturns} from "../core/Dispatcher";
|
|
|
|
declare module "./type" {
|
|
interface GenericReturn<Params> {
|
|
// Jos: not sure how to define this or why it is needed
|
|
// square: Signature<Params, [T], T>
|
|
// square: ConservativeUnary<Params, T>
|
|
// square: Params extends [infer R]
|
|
// ? R extends number ? UnderlyingReal<R> : 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 =
|
|
<T>(dep: Dependency<'multiply', [T, T]>):
|
|
ImpType<'square', [T]> =>
|
|
z => dep.multiply(z, z)
|