feat: Runtime type reflection #17

Merged
glen merged 21 commits from ts-macros-issues into main 2023-10-17 22:02:18 +00:00
5 changed files with 11 additions and 10 deletions
Showing only changes of commit 20236355c1 - Show all commits

View File

@ -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',

View File

@ -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>>

View File

@ -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

View File

@ -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)
}

View File

@ -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