get template literals working with multiple dependencies
This commit is contained in:
parent
722ee05a0a
commit
7dc26ea297
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@
|
|||||||
# Typescript
|
# Typescript
|
||||||
# emitted code
|
# emitted code
|
||||||
obj
|
obj
|
||||||
|
build
|
||||||
|
|
||||||
# ---> Node
|
# ---> Node
|
||||||
# Logs
|
# Logs
|
||||||
|
@ -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',
|
||||||
|
@ -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
|
||||||
|
84
src/infer.ts
84
src/infer.ts
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"outDir": "./obj"
|
"outDir": "./build"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user