experiment inferring TS types from a JS template
This commit is contained in:
parent
a5848125e4
commit
11792e0435
57
src/infer.ts
Normal file
57
src/infer.ts
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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 ResolveTuple<T> =
|
||||
T extends K ? [ResolveType<T>] :
|
||||
T extends `${infer L extends K}, ${infer M extends K}` ? [ResolveType<L>, ResolveType<M>] :
|
||||
T extends `${infer L extends K}, ${infer M extends K}, ${infer N extends K}`
|
||||
? [ResolveType<L>, ResolveType<M>, ResolveType<N>]
|
||||
: never
|
||||
|
||||
type ResolveFunction<T> =
|
||||
T extends `${infer Name}(${infer Args}) : ${infer L extends K}`
|
||||
? (...args: ResolveTuple<Args>) => ResolveType<L>
|
||||
: never
|
||||
|
||||
return function create<T extends string, U extends string, V>(
|
||||
dependencies: { [L in T]: U },
|
||||
callback: (deps: { [L in T]: ResolveFunction<U> }) => V
|
||||
) {
|
||||
return callback
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user