feat: add example of specifying dependencies and signature with runtime vals
This commit is contained in:
parent
cc1e66c054
commit
ed2ae1b006
@ -18,6 +18,8 @@
|
||||
url: 'https://code.studioinfinity.org/glen/typocomath.git',
|
||||
},
|
||||
devDependencies: {
|
||||
'@types/node': '^20.5.0',
|
||||
'source-map': '^0.7.4',
|
||||
typescript: '^4.9.3',
|
||||
},
|
||||
}
|
||||
|
@ -1,14 +1,32 @@
|
||||
lockfileVersion: 5.4
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
specifiers:
|
||||
typescript: ^4.9.3
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
devDependencies:
|
||||
typescript: 4.9.3
|
||||
'@types/node':
|
||||
specifier: ^20.5.0
|
||||
version: 20.5.0
|
||||
source-map:
|
||||
specifier: ^0.7.4
|
||||
version: 0.7.4
|
||||
typescript:
|
||||
specifier: ^4.9.3
|
||||
version: 4.9.3
|
||||
|
||||
packages:
|
||||
|
||||
/typescript/4.9.3:
|
||||
/@types/node@20.5.0:
|
||||
resolution: {integrity: sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==}
|
||||
dev: true
|
||||
|
||||
/source-map@0.7.4:
|
||||
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
|
||||
engines: {node: '>= 8'}
|
||||
dev: true
|
||||
|
||||
/typescript@4.9.3:
|
||||
resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==}
|
||||
engines: {node: '>=4.2.0'}
|
||||
hasBin: true
|
||||
|
@ -1,5 +1,32 @@
|
||||
import type {Dependencies, Signature} from '../interfaces/type.js'
|
||||
|
||||
export const square =
|
||||
<T>(dep: Dependencies<'multiply', T>): Signature<'square', T> =>
|
||||
z => dep.multiply(z, z)
|
||||
// This stuff would really go in interfaces/type.js or someplace like that
|
||||
type Annotate<U> = U & {dependencies?: Record<string, string>, signature?: string}
|
||||
|
||||
function genericImplementation<Deps extends Record<string, string>, Sig extends string>(
|
||||
deps: Deps, sig: Sig, impl: <T>(dep: Dependencies<keyof Deps, T>) => Signature<Sig, T>
|
||||
) {
|
||||
const rimpl: Annotate<typeof impl> = impl
|
||||
rimpl.dependencies = deps
|
||||
rimpl.signature = sig
|
||||
return rimpl
|
||||
}
|
||||
// and of course it would need to be generalized somewhat from the above
|
||||
// --------------
|
||||
|
||||
// Then here for the implementation we would have:
|
||||
export const square = genericImplementation(
|
||||
{multiply: 'T'}, 'square', <T>(dep) => z => dep.multiply(z, z)
|
||||
)
|
||||
|
||||
// Note this was previously
|
||||
|
||||
// export const square =
|
||||
// <T>(dep: Dependencies<'multiply', T>): Signature<'square', T> =>
|
||||
// z => dep.multiply(z, z)
|
||||
|
||||
// but then we couldn't get at the dependencies or the signature at runtime. So the point of
|
||||
// genericImplementation is that it takes literal values for the dependencies and signature,
|
||||
// from which it deduces the types of the actual dependencies of the implementation and the
|
||||
// the implementation itself, and then it copies those literal values onto properties of the
|
||||
// implementation, where they can be accessed at runtime as illustreated in ../index.ts
|
||||
|
11
src/index.ts
11
src/index.ts
@ -18,3 +18,14 @@ const myabs = quatAbsquare({re: {re: 0, im: 1}, im: {re:2, im: 3}})
|
||||
const typeTest: typeof myabs = 7 // check myabs is just a number
|
||||
|
||||
console.log('Result is', myabs)
|
||||
|
||||
console.log('Dependencies of square are', Specifications.generic.square.dependencies)
|
||||
console.log('Signature of square is', Specifications.generic.square.signature)
|
||||
|
||||
const realSquare = Specifications.generic.square<number>({multiply: (a,b) => a*b})
|
||||
console.log('Square of 2.5 is', realSquare(2.5))
|
||||
|
||||
// and note the following fail with a type error as desired:
|
||||
// const fakeSquare = Specifications.generic.square<number>({multiply: (a,b,c) => a*b*c})
|
||||
// const stringSquare = Specifications.generic.square<string>({multiply: (a,b) => a*b})
|
||||
// console.log('Square of three is', stringSquare('three'))
|
||||
|
@ -68,8 +68,8 @@ export interface Signatures<T> {
|
||||
|
||||
type SignatureKey<T> = keyof Signatures<T>
|
||||
|
||||
export type Signature<Name extends SignatureKey<T>, T> = Signatures<T>[Name]
|
||||
export type Signature<Name, T> = Signatures<T>[Name & SignatureKey<T>]
|
||||
export type Returns<Name extends SignatureKey<T>, T> = ReturnType<Signatures<T>[Name]>
|
||||
export type Dependencies<Name extends SignatureKey<T>, T> = {[K in Name]: Signature<K, T>}
|
||||
export type Dependencies<Name, T> = {[K in Name & SignatureKey<T>]: Signature<K, T>}
|
||||
|
||||
export type AliasOf<Name extends string, T> = T & {aliasOf?: Name}
|
||||
|
@ -2,6 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"rootDir": "./src",
|
||||
"outDir": "./obj"
|
||||
"outDir": "./obj",
|
||||
"moduleResolution": "nodenext"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user