feat: Runtime type reflection #17
@ -7,7 +7,7 @@
|
||||
test: 'echo "Error: no test specified" && exit 1',
|
||||
build: 'mkdirp build && cpy etc/package.json build --flat && tsc',
|
||||
start: 'node build',
|
||||
go: 'pnpm --sequential "/clean|build|start/"',
|
||||
go: 'pnpm clean && pnpm build && pnpm start',
|
||||
clean: 'del-cli build',
|
||||
},
|
||||
packageManager: 'pnpm',
|
||||
|
@ -2,7 +2,7 @@ import {Complex} from './type.js'
|
||||
import type {
|
||||
Dependencies, Signature, Returns, RealType, AliasOf
|
||||
} from '../interfaces/type.js'
|
||||
import {$implement} from '../interfaces/type.js'
|
||||
import {$reflect} from '../interfaces/type.js'
|
||||
|
||||
declare module "../interfaces/type" {
|
||||
interface Signatures<T> {
|
||||
@ -74,7 +74,7 @@ export const divide =
|
||||
// and we have to get it straight which operations we need on each type, and
|
||||
// in fact, we need `addReal` on both T and Complex<T>, hence the dependency
|
||||
// with a custom name, not generated via Dependencies<...>
|
||||
$implement!('sqrt',
|
||||
export const sqrt = $reflect!('sqrt',
|
||||
<T>(dep: Dependencies<'equal' | 'conservativeSqrt' | 'unaryMinus', RealType<T>>
|
||||
& Dependencies<'zero' | 'complex', T>
|
||||
& Dependencies<'absquare' | 're' | 'divideReal', Complex<T>>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type {Dependencies, Signature} from '../interfaces/type.js'
|
||||
import {$implement} from '../interfaces/type.js'
|
||||
import {$reflect} from '../interfaces/type.js'
|
||||
|
||||
$implement!('square',
|
||||
export const square = $reflect!('square',
|
||||
<T>(dep: Dependencies<'multiply', T>) => (z:T) => dep.multiply(z, z))
|
||||
// z => dep.fooBar(z, z) // fails as desired
|
||||
// z => dep.multiply(z, 'foo') // still fails as desired
|
||||
|
@ -82,7 +82,8 @@ export type Dependencies<Name extends SignatureKey<T>, T> = Deps<{[K in Name]: S
|
||||
export type AliasOf<Name extends string, T> = T & {aliasOf?: Name}
|
||||
|
||||
// For defining implementations with type reflection
|
||||
export function $implement<Impl>(name: string, expr: Impl) {
|
||||
$$define!(name, expr, false, true); // Final `true` is export
|
||||
export function $reflect<Impl>(name: string, expr: Impl) : Impl & { reflectedType: string} {
|
||||
$$define!(name, expr, false, false);
|
||||
$$ident!(name).reflectedType = $$typeToString!<Impl>(true, false, true);
|
||||
return $$ident!(name)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type {configDependency} from '../core/Config.js'
|
||||
import type {Dependencies, Signature} from '../interfaces/type.js'
|
||||
import { $implement } from '../interfaces/type.js'
|
||||
import { $reflect } from '../interfaces/type.js'
|
||||
|
||||
export const add: Signature<'add', number> = (a, b) => a + b
|
||||
export const unaryMinus: Signature<'unaryMinus', number> = a => -a
|
||||
@ -11,10 +11,10 @@ export const absquare: Signature<'absquare', number> = a => a * a
|
||||
export const reciprocal: Signature<'reciprocal', number> = a => 1 / a
|
||||
export const divide: Signature<'divide', number> = (a, b) => a / b
|
||||
|
||||
const basicSqrt = a => isNaN(a) ? NaN : Math.sqrt(a)
|
||||
const basicSqrt = (a: number) => isNaN(a) ? NaN : Math.sqrt(a)
|
||||
export const conservativeSqrt: Signature<'conservativeSqrt', number> = basicSqrt
|
||||
|
||||
$implement!('sqrt',
|
||||
export const sqrt = $reflect!('sqrt',
|
||||
(dep: configDependency & Dependencies<'complex', number>): Signature<'sqrt', number> => {
|
||||
if (dep.config.predictable || !dep.complex) {
|
||||
return basicSqrt
|
||||
|
Loading…
Reference in New Issue
Block a user