From ed2ae1b00669bfd3e750e46193c41a042586039f Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Fri, 18 Aug 2023 02:40:05 -0700 Subject: [PATCH] feat: add example of specifying dependencies and signature with runtime vals --- package.json5 | 2 ++ pnpm-lock.yaml | 28 +++++++++++++++++++++++----- src/generic/arithmetic.ts | 33 ++++++++++++++++++++++++++++++--- src/index.ts | 11 +++++++++++ src/interfaces/type.ts | 4 ++-- tsconfig.json | 3 ++- 6 files changed, 70 insertions(+), 11 deletions(-) diff --git a/package.json5 b/package.json5 index 874d5e3..fcfeb46 100644 --- a/package.json5 +++ b/package.json5 @@ -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', }, } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 095704b..76cb316 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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 diff --git a/src/generic/arithmetic.ts b/src/generic/arithmetic.ts index 78ad57d..e00c4e6 100644 --- a/src/generic/arithmetic.ts +++ b/src/generic/arithmetic.ts @@ -1,5 +1,32 @@ import type {Dependencies, Signature} from '../interfaces/type.js' -export const square = - (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 & {dependencies?: Record, signature?: string} + +function genericImplementation, Sig extends string>( + deps: Deps, sig: Sig, impl: (dep: Dependencies) => Signature +) { + const rimpl: Annotate = 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', (dep) => z => dep.multiply(z, z) +) + +// Note this was previously + +// export const square = +// (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 diff --git a/src/index.ts b/src/index.ts index 297b271..397fd7f 100644 --- a/src/index.ts +++ b/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({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({multiply: (a,b,c) => a*b*c}) +// const stringSquare = Specifications.generic.square({multiply: (a,b) => a*b}) +// console.log('Square of three is', stringSquare('three')) diff --git a/src/interfaces/type.ts b/src/interfaces/type.ts index 9e6870d..7dbf276 100644 --- a/src/interfaces/type.ts +++ b/src/interfaces/type.ts @@ -68,8 +68,8 @@ export interface Signatures { type SignatureKey = keyof Signatures -export type Signature, T> = Signatures[Name] +export type Signature = Signatures[Name & SignatureKey] export type Returns, T> = ReturnType[Name]> -export type Dependencies, T> = {[K in Name]: Signature} +export type Dependencies = {[K in Name & SignatureKey]: Signature} export type AliasOf = T & {aliasOf?: Name} diff --git a/tsconfig.json b/tsconfig.json index aae3a94..b45999b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "target": "ES2022", "rootDir": "./src", - "outDir": "./obj" + "outDir": "./obj", + "moduleResolution": "nodenext" } }