58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
/**
|
|
* Idea: instead of writing TypeScript, and inferring the JS-pocomath signature
|
|
* from TS that via a TypeScript plugin, we can maybe do this the other way
|
|
* around: take the JS-pocomath signature as base (and source of truth), and
|
|
* infer TypeScript interfaces from that using infer in template literal types.
|
|
*/
|
|
|
|
type T = {} // TODO: how to do generics?
|
|
|
|
const create = createFactory<{
|
|
number: number
|
|
bigint: bigint
|
|
T: T // TODO: how to do generics?
|
|
'Complex<T>': unknown // TODO: how to do generics?
|
|
}>()
|
|
|
|
|
|
// TODO: how to pass config?
|
|
// FIXME: multiple signatures do not work
|
|
|
|
const createSquare = create({
|
|
multiply: '(number, number) : number',
|
|
// zero: '(number) : number'
|
|
},dep => {
|
|
return (x: number) => dep.multiply(x, x)
|
|
}
|
|
)
|
|
|
|
// the code works in JS, and works in TS
|
|
const multiply = (a: number, b: number) => a * b
|
|
const square = createSquare({ multiply })
|
|
console.log('square', square(8)) // 64
|
|
|
|
function createFactory<BaseTypes extends Record<string, unknown>>() {
|
|
type K = string & keyof BaseTypes
|
|
|
|
type ResolveType<T extends K> = BaseTypes[T]
|
|
|
|
type ResolveArguments<S extends string> =
|
|
S extends '' ? [] :
|
|
S extends `${infer T extends K}, ${infer U}`
|
|
? [ResolveType<T>, ...ResolveArguments<U>]
|
|
: S extends `${infer T extends K}` ? [ResolveType<T>]
|
|
: never;
|
|
|
|
type ResolveFunctionDef<T> =
|
|
T extends `${infer Name}(${infer Args}) : ${infer L extends K}`
|
|
? (...args: ResolveArguments<Args>) => ResolveType<L>
|
|
: never
|
|
|
|
return function create<T extends string, U extends string, V>(
|
|
dependencies: { [L in T]: U },
|
|
callback: (deps: { [L in T]: ResolveFunctionDef<U> }) => V
|
|
) {
|
|
return callback
|
|
}
|
|
}
|