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 {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" {
|
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]>) =>
|
export const typeImps = <T>() => ({
|
||||||
(t: T) => ({re: t, im: dep.zero(t)})
|
complex_unary: (dep: Dependency<'zero', [T]>) =>
|
||||||
export const complex_binary = <T>(t: T, u: T) => ({re: t, im: u})
|
(t: T) => ({re: t, im: dep.zero(t)}),
|
||||||
|
complex_binary: (t: T, u: T) => ({re: t, im: u})
|
||||||
|
})
|
||||||
|
@ -11,14 +11,15 @@ type TypeName = string
|
|||||||
type Parameter = TypeName
|
type Parameter = TypeName
|
||||||
type Signature = Parameter[]
|
type Signature = Parameter[]
|
||||||
|
|
||||||
export interface ImplementationTypes {}
|
export interface ImplementationTypes<T> {}
|
||||||
export type typeOfDependency = {typeOf: (x: unknown) => TypeName}
|
export type typeOfDependency = {typeOf: (x: unknown) => TypeName}
|
||||||
|
|
||||||
// Helper for collecting implementations
|
// Helper for collecting implementations
|
||||||
// (Really just suffixes the type name onto the keys of exports)
|
// (Really just suffixes the type name onto the keys of exports)
|
||||||
export type ForType<T extends string, Exports> = keyof Exports extends string
|
export type ForType<Suffix extends string, Exports> =
|
||||||
? {[K in keyof Exports as `${K}_${T}`]: Exports[K]}
|
keyof Exports extends string
|
||||||
: never
|
? {[K in keyof Exports as `${K}_${Suffix}`]: Exports[K]}
|
||||||
|
: never
|
||||||
|
|
||||||
//dummy implementation for now
|
//dummy implementation for now
|
||||||
export function joinTypes(a: TypeName, b: TypeName) {
|
export function joinTypes(a: TypeName, b: TypeName) {
|
||||||
@ -37,6 +38,18 @@ type FinalShape<FuncType> =
|
|||||||
|
|
||||||
type BeginsWith<Name extends string> = `${Name}${string}`
|
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[]> =
|
type DependencyTypes<Ob, Name extends string, Params extends unknown[]> =
|
||||||
{[K in keyof Ob]: K extends BeginsWith<Name>
|
{[K in keyof Ob]: K extends BeginsWith<Name>
|
||||||
? FinalShape<Ob[K]> extends (...args: Params) => any
|
? 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[]> =
|
export type Dependency<Name extends string, Params extends unknown[]> =
|
||||||
{[N in Name]:
|
{[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
|
// Now types used in the Dispatcher class itself
|
||||||
|
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
import {ForType} from '../core/Dispatcher.js'
|
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" {
|
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 {configDependency} from '../core/Config.js'
|
||||||
import {Dependency} from '../core/Dispatcher.js'
|
import {Dependency} from '../core/Dispatcher.js'
|
||||||
|
|
||||||
export const add = (a: number, b: number) => a + b
|
const unaryMinus = (a: number) => -a
|
||||||
export const unaryMinus = (a: number) => -a
|
|
||||||
export const subtract = (a: number, b: number) => a - b
|
export const arithmeticImps = <T>() => ({
|
||||||
export const multiply = (a: number, b: number) => a * b
|
add: (a: number, b: number) => a + b,
|
||||||
export const divide = (a: number, b: number) => a / b
|
unaryMinus,
|
||||||
export const sqrt =
|
subtract: (a: number, b: number) => a - b,
|
||||||
|
multiply: (a: number, b: number) => a * b,
|
||||||
|
divide: (a: number, b: number) => a / b,
|
||||||
|
sqrt:
|
||||||
(dep: configDependency
|
(dep: configDependency
|
||||||
& Dependency<'complex', [number, number]>) => {
|
& Dependency<'complex', [number, number]>) => {
|
||||||
if (dep.config.predictable || !dep.complex) {
|
if (dep.config.predictable || !dep.complex) {
|
||||||
@ -18,3 +21,4 @@ export const sqrt =
|
|||||||
return dep.complex(0, Math.sqrt(unaryMinus(a)))
|
return dep.complex(0, Math.sqrt(unaryMinus(a)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
@ -4,4 +4,6 @@ export const number_type = {
|
|||||||
from: {string: s => +s}
|
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