diff --git a/src/core/Type.js b/src/core/Type.js index ff07f60..fec409f 100644 --- a/src/core/Type.js +++ b/src/core/Type.js @@ -1,13 +1,22 @@ -export class Type { +export class Type extends Function { constructor(f, options = {}) { + super() this.test = f this.from = options.from ?? {patterns: []} // mock empty Implementations if ('zero' in options) this.zero = options.zero if ('one' in options) this.one = options.one if ('nan' in options) this.nan = options.nan + + return new Proxy(this, { + apply: (target, thisForCall, args) => { + const callThrough = thisForCall ?? target + if (callThrough.specialize) return callThrough.specialize(...args) + throw new TypeError(`Type ${callThrough} is not generic`) + }, + }) } toString() { - return this.name || `[Type ${this.test}]` + return this.typeName || `[Type ${this.test}]` } } diff --git a/src/core/TypeDispatcher.js b/src/core/TypeDispatcher.js index 88ed393..ccfc3ad 100644 --- a/src/core/TypeDispatcher.js +++ b/src/core/TypeDispatcher.js @@ -84,7 +84,7 @@ export class TypeDispatcher { throw new TypeError(`attempt to merge unusable type '${val}'`) } this.types[key] = val - val.name = key + val.typeName = key continue } diff --git a/src/core/__test__/TypeDispatcher.spec.js b/src/core/__test__/TypeDispatcher.spec.js index 25ed721..a5fdac8 100644 --- a/src/core/__test__/TypeDispatcher.spec.js +++ b/src/core/__test__/TypeDispatcher.spec.js @@ -3,6 +3,7 @@ import {TypeDispatcher} from '../TypeDispatcher.js' import * as booleans from '#boolean/all.js' import * as generics from '#generic/all.js' import * as numbers from '#number/all.js' +import {NumberT} from '#number/NumberT.js' import {onType, ResolutionError} from "#core/helpers.js" import {Any} from "#core/TypePatterns.js" import {Returns, NotAType} from "#core/Type.js" @@ -68,4 +69,7 @@ describe('TypeDispatcher', () => { const doomed = new TypeDispatcher() assert.throws(() => doomed.merge({NaT: NotAType}), TypeError) }) + it('supports generic types', () => { + assert.throws(() => NumberT(0), TypeError) + }) })