get template literals working with multiple dependencies

This commit is contained in:
Jos de Jong 2023-09-14 17:42:42 +02:00
parent 722ee05a0a
commit 7dc26ea297
6 changed files with 63 additions and 41 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
# Typescript # Typescript
# emitted code # emitted code
obj obj
build
# ---> Node # ---> Node
# Logs # Logs

View File

@ -1,3 +1,3 @@
# typocomath # typocomath
A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state. A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state.

View File

@ -4,7 +4,7 @@
description: 'A hopeful final typescipt-pragmatic mathjs proof-of-concept', description: 'A hopeful final typescipt-pragmatic mathjs proof-of-concept',
main: 'index.ts', main: 'index.ts',
scripts: { scripts: {
test: 'echo "Error: no test specified" && exit 1', go: 'tsc && node build/infer.js'
}, },
keywords: [ keywords: [
'math', 'math',

View File

@ -1,14 +1,17 @@
lockfileVersion: 5.4 lockfileVersion: '6.0'
specifiers: settings:
typescript: ^4.9.3 autoInstallPeers: true
excludeLinksFromLockfile: false
devDependencies: devDependencies:
typescript: 4.9.3 typescript:
specifier: ^4.9.3
version: 4.9.3
packages: packages:
/typescript/4.9.3: /typescript@4.9.3:
resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==}
engines: {node: '>=4.2.0'} engines: {node: '>=4.2.0'}
hasBin: true hasBin: true

View File

@ -5,53 +5,71 @@
* infer TypeScript interfaces from that using infer in template literal types. * infer TypeScript interfaces from that using infer in template literal types.
*/ */
type T = {} // TODO: how to do generics?
const create = createFactory<{ const create = createFactory<{
number: number number: number
bigint: bigint bigint: bigint
T: T // TODO: how to do generics? string: string
'Complex<T>': unknown // TODO: how to do generics? // T: T // TODO: how to do generics?
// 'Complex<T>': unknown // TODO: how to do generics?
}>() }>()
// TODO: how to pass config? // TODO: how to pass config?
// FIXME: multiple signatures do not work // These are the interfaces:
const Multiply = 'multiply(number,number)=>number'
const Zero = 'zero(number)=>number'
const createSquare = create({ const createSquare = create([Multiply, Zero],dep => {
multiply: '(number, number) : number', return (x: number) => dep.multiply(x, x)
// zero: '(number) : number' })
},dep => {
return (x: number) => dep.multiply(x, x)
}
)
// the code works in JS, and works in TS // the code works in JS, and works in TS
const multiply = (a: number, b: number) => a * b const multiply = (a: number, b: number) => a * b
const square = createSquare({ multiply }) const zero = (a: number) => 0
const square = createSquare({ multiply, zero })
console.log('square', square(8)) // 64 console.log('square', square(8)) // 64
function createFactory<BaseTypes extends Record<string, unknown>>() { function createFactory<BaseTypes extends Record<string, unknown>>() {
type K = string & keyof BaseTypes type BaseTypeNames = string & keyof BaseTypes
type ResolveType<TypeName extends BaseTypeNames> = BaseTypes[TypeName]
type ResolveType<T extends K> = BaseTypes[T] type Value<K> = K
type ResolveArguments<S extends string> = type ResolveArguments<S extends string> = S extends ''
S extends '' ? [] : ? []
S extends `${infer T extends K}, ${infer U}` : S extends `${infer Arg extends BaseTypeNames},${infer Tail}`
? [ResolveType<T>, ...ResolveArguments<U>] ? [ResolveType<Arg>, ...ResolveArguments<Tail>]
: S extends `${infer T extends K}` ? [ResolveType<T>] : S extends `${infer Arg extends BaseTypeNames}`
: never; ? [ResolveType<Arg>]
: never
type ResolveFunctionDef<T> = type FunctionDefinition<FnType> =
T extends `${infer Name}(${infer Args}) : ${infer L extends K}` FnType extends Value<infer K>
? (...args: ResolveArguments<Args>) => ResolveType<L> ? K extends `${infer Name}(${infer Args})=>${infer ReturnType extends BaseTypeNames}`
: never ? Record<Name, (...args: ResolveArguments<Args>) => ResolveType<ReturnType>>
: never
: never
return function create<T extends string, U extends string, V>( // inspired by: https://stackoverflow.com/questions/68391632/infer-type-from-array-literal
dependencies: { [L in T]: U }, type DepRecord<
callback: (deps: { [L in T]: ResolveFunctionDef<U> }) => V Arr extends Array<Value<any>>,
) { Result extends Record<string, any> = {}
return callback > = Arr extends []
} ? Result
: Arr extends [infer H, ...infer Tail]
? Tail extends Array<Value<any>>
? H extends Value<any>
? DepRecord<Tail, Result & FunctionDefinition<H>>
: never
: never
: never
return function create<K extends string, Dependencies extends Value<K>[], W>(
dependencies: [...Dependencies],
callback: (deps: DepRecord<[...Dependencies]>) => W
) {
console.log('Creating typed-function with dependencies:', dependencies)
// TODO: create a typed-function for real
return callback
}
} }

View File

@ -2,6 +2,6 @@
"compilerOptions": { "compilerOptions": {
"target": "ES2022", "target": "ES2022",
"rootDir": "./src", "rootDir": "./src",
"outDir": "./obj" "outDir": "./build"
} }
} }