refactor: Put all implementations in a single generic
This change eases type inference of return types.
This commit is contained in:
parent
3fa216d1f4
commit
40d05045fc
@ -1,8 +1,9 @@
|
||||
import {ForType} from '../core/Dispatcher.js'
|
||||
import * as Complex from './native.js'
|
||||
import {Complex_type, typeImps} from './type.js'
|
||||
|
||||
export {Complex}
|
||||
export const Complex_bundle = Object.assign({Complex_type}, typeImps())
|
||||
|
||||
declare module "../core/Dispatcher" {
|
||||
interface ImplementationTypes extends ForType<'Complex', typeof Complex> {}
|
||||
interface ImplementationTypes<T> extends
|
||||
ForType<'Complex', ReturnType<typeof typeImps<T>>> {}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ export const Complex_type = {
|
||||
}
|
||||
}
|
||||
|
||||
export const complex_unary = <T>(dep: Dependency<'zero', [T]>) =>
|
||||
(t: T) => ({re: t, im: dep.zero(t)})
|
||||
export const complex_binary = <T>(t: T, u: T) => ({re: t, im: u})
|
||||
export const typeImps = <T>() => ({
|
||||
complex_unary: (dep: Dependency<'zero', [T]>) =>
|
||||
(t: T) => ({re: t, im: dep.zero(t)}),
|
||||
complex_binary: (t: T, u: T) => ({re: t, im: u})
|
||||
})
|
||||
|
@ -11,13 +11,14 @@ type TypeName = string
|
||||
type Parameter = TypeName
|
||||
type Signature = Parameter[]
|
||||
|
||||
export interface ImplementationTypes {}
|
||||
export interface ImplementationTypes<T> {}
|
||||
export type typeOfDependency = {typeOf: (x: unknown) => TypeName}
|
||||
|
||||
// Helper for collecting implementations
|
||||
// (Really just suffixes the type name onto the keys of exports)
|
||||
export type ForType<T extends string, Exports> = keyof Exports extends string
|
||||
? {[K in keyof Exports as `${K}_${T}`]: Exports[K]}
|
||||
export type ForType<Suffix extends string, Exports> =
|
||||
keyof Exports extends string
|
||||
? {[K in keyof Exports as `${K}_${Suffix}`]: Exports[K]}
|
||||
: never
|
||||
|
||||
//dummy implementation for now
|
||||
@ -37,6 +38,18 @@ type FinalShape<FuncType> =
|
||||
|
||||
type BeginsWith<Name extends string> = `${Name}${string}`
|
||||
|
||||
type ImpNames = keyof ImplementationTypes<unknown>
|
||||
|
||||
type MatchingParams<Name extends string, Params extends unknown[], T> =
|
||||
{[K in ImpNames]: K extends BeginsWith<Name>
|
||||
? FinalShape<ImplementationTypes<T>[K]> extends (...args: Params) => any
|
||||
? Parameters<FinalShape<ImplementationTypes<T>[K]>>
|
||||
: never
|
||||
: never}[ImpNames]
|
||||
|
||||
export type BestType<Name extends string, Params extends unknown[]> =
|
||||
Params extends MatchingParams<Name, Params, infer T> ? T : unknown
|
||||
|
||||
type DependencyTypes<Ob, Name extends string, Params extends unknown[]> =
|
||||
{[K in keyof Ob]: K extends BeginsWith<Name>
|
||||
? FinalShape<Ob[K]> extends (...args: Params) => any
|
||||
@ -46,7 +59,7 @@ type DependencyTypes<Ob, Name extends string, Params extends unknown[]> =
|
||||
|
||||
export type Dependency<Name extends string, Params extends unknown[]> =
|
||||
{[N in Name]:
|
||||
DependencyTypes<ImplementationTypes, N, Params>[keyof ImplementationTypes]}
|
||||
DependencyTypes<ImplementationTypes<BestType<N, Params>>, N, Params>[ImpNames]}
|
||||
|
||||
// Now types used in the Dispatcher class itself
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
import {ForType} from '../core/Dispatcher.js'
|
||||
import * as numbers from './native.js'
|
||||
import {number_type, typeImps} from './type.js'
|
||||
import {arithmeticImps} from './arithmetic.js'
|
||||
|
||||
export {numbers}
|
||||
export const numbers_bundle =
|
||||
Object.assign({number_type}, typeImps(), arithmeticImps())
|
||||
|
||||
declare module "../core/Dispatcher" {
|
||||
interface ImplementationTypes extends ForType<'numbers', typeof numbers> {}
|
||||
interface ImplementationTypes<T> extends
|
||||
ForType<'numbers', ReturnType<typeof typeImps<T>>> {}
|
||||
interface ImplementationTypes<T> extends
|
||||
ForType<'numbers', ReturnType<typeof arithmeticImps<T>>> {}
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
import {configDependency} from '../core/Config.js'
|
||||
import {Dependency} from '../core/Dispatcher.js'
|
||||
|
||||
export const add = (a: number, b: number) => a + b
|
||||
export const unaryMinus = (a: number) => -a
|
||||
export const subtract = (a: number, b: number) => a - b
|
||||
export const multiply = (a: number, b: number) => a * b
|
||||
export const divide = (a: number, b: number) => a / b
|
||||
export const sqrt =
|
||||
const unaryMinus = (a: number) => -a
|
||||
|
||||
export const arithmeticImps = <T>() => ({
|
||||
add: (a: number, b: number) => a + b,
|
||||
unaryMinus,
|
||||
subtract: (a: number, b: number) => a - b,
|
||||
multiply: (a: number, b: number) => a * b,
|
||||
divide: (a: number, b: number) => a / b,
|
||||
sqrt:
|
||||
(dep: configDependency
|
||||
& Dependency<'complex', [number, number]>) => {
|
||||
if (dep.config.predictable || !dep.complex) {
|
||||
@ -18,3 +21,4 @@ export const sqrt =
|
||||
return dep.complex(0, Math.sqrt(unaryMinus(a)))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -4,4 +4,6 @@ export const number_type = {
|
||||
from: {string: s => +s}
|
||||
}
|
||||
|
||||
export const zero = (a: number) => 0
|
||||
export const typeImps = <T>() => ({
|
||||
zero: (a: number) => 0
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user