105 lines
3.1 KiB
TypeScript
105 lines
3.1 KiB
TypeScript
import { useTypes } from 'over.ts';
|
|
|
|
const types = {
|
|
number: (x: unknown): x is number => typeof x === 'number',
|
|
bigint: (x: unknown): x is bigint => typeof x === 'bigint'
|
|
}
|
|
|
|
const overload = useTypes(types)
|
|
|
|
type TypeName = keyof typeof types
|
|
|
|
//type Tuple<T> = T | `${T}, ${Tuple<T>}`
|
|
//type TypeTuple = Tuple<TypeName>
|
|
|
|
type CheckTuple<T> = T extends TypeName
|
|
? T
|
|
: T extends `${TypeName}, ${infer Rest}`
|
|
? CheckTuple<Rest> extends string ? T : false
|
|
: false
|
|
|
|
type CheckDecl<T> = T extends `${infer Args} -> ${TypeName}`
|
|
? CheckTuple<Args> extends string ? T : never
|
|
: never
|
|
|
|
function check<T extends string>(d: CheckDecl<T>) {
|
|
console.log(d)
|
|
}
|
|
|
|
check('number, bigint -> bigint')
|
|
check('bigint -> number')
|
|
|
|
// check('string -> number') // would be error as desired
|
|
|
|
class ImpBuilder {
|
|
addImp<T extends string, U>(decl: CheckDecl<T>, imp: U) {
|
|
return Object.assign(this, {[decl]: imp} as Record<T, U>)
|
|
}
|
|
// finalize<T extends Record<string, unknown>>(this: T) {
|
|
// return overload(this as Omit<T, 'addImp' | 'finalize'>)
|
|
// }
|
|
finalize() {
|
|
delete this.addImp
|
|
delete this.finalize
|
|
return this
|
|
}
|
|
}
|
|
|
|
function fixImps<T extends {addImp: any}>(imps: T): Omit<T, 'addImp'> {
|
|
const res = Object.assign({}, imps)
|
|
delete res.addImp
|
|
return res
|
|
}
|
|
|
|
function overloadImps<T>(imps: T) {
|
|
return overload(imps)
|
|
}
|
|
|
|
const negateImps = new ImpBuilder()
|
|
.addImp('number -> number', (a: number) => -a)
|
|
.addImp('bigint -> bigint', (a: bigint) => -a)
|
|
|
|
const negate = overload(negateImps.finalize() as Omit<typeof negateImps, 'finalize'|'addImp'>)
|
|
|
|
console.log('Negation of 5 is', negate(5))
|
|
console.log('Negation of 5n is', negate(5n))
|
|
|
|
const addImps = new ImpBuilder() // imagining this is in some "initialize a proto-bundle" file
|
|
addImps.addImp('number, number -> number', (a: number, b: number) => a+b) // imagining this line in the `number` file
|
|
const addAll = addImps.addImp('bigint, bigint -> bigint', (a: bigint, b: bigint) => a+b) // and this is in the `bigint` file
|
|
const add = overload(addAll.finalize() as Omit<typeof addAll, 'finalize'|'addImp'>) // We wrap everything up elsewhere
|
|
|
|
// This should **NOT** be an error but sadly it is:
|
|
//@ts-expect-error
|
|
console.log('Sum of 5 and 7 is', add(5,7))
|
|
console.log('Sum of 5n and 7n is', add(5n, 7n))
|
|
|
|
try {
|
|
//@ts-expect-error
|
|
console.log('Mixed sum is', add(5n, 7))
|
|
} catch {
|
|
console.log('Mixed sum errored as expected.')
|
|
}
|
|
|
|
/*****
|
|
const addImps = new ImpBuilder()
|
|
//addImps.addImp('number, number -> number', (a: number, b: number) => a+b)
|
|
const subAddImps = addImps.addImp('number, number -> number', (a: number, b: number) => a+b).addImp('bigint, bigint -> bigint', (a: bigint, b: bigint) => {
|
|
console.log('adding bigints')
|
|
return a+b
|
|
})
|
|
//const finalAddImps = addImps.finalize()
|
|
|
|
const add = overload(subAddImps.finalize() as Omit<typeof subAddImps, 'finalize'|'addImp'>)
|
|
|
|
console.log('Sum of 5 and 7 is', add(5,7))
|
|
console.log('Sum of 5n and 7n is', add(5n, 7n))
|
|
|
|
try {
|
|
//@ts-expect-error
|
|
console.log('Mixed sum is', add(5n, 7))
|
|
} catch {
|
|
console.log('Mixed sum errored as expected.')
|
|
}
|
|
****/
|