jaredwray / fumanchu

Handlebars + Helpers Together :heart:
https://fumanchu.org
MIT License
11 stars 2 forks source link

"handlebars.create is not a function" (wrong TypeScript type declarations?) #46

Closed francescosalvi closed 3 months ago

francescosalvi commented 4 months ago

Repro

Given the example file src/index.ts

import handlebars from '@jaredwray/fumanchu';
const newHandlebarsInstance = handlebars.create();

running tsc produces no errors, while node dist/index.js gives:

const newHandlebarsInstance = handlebars.create();
                                         ^

TypeError: handlebars.create is not a function
    at file:///tmp/fumanchu-fiddle/dist/index.js:2:42
    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/modules/run_main:66:12)

It seems to me the package is declaring its types as "the same as handlebar's", but that contradicts the actual implementation of the package index module.


tsconfig.json

{
    "compilerOptions": {
      "target": "ESNext",
      "module": "ESNext",
      "moduleResolution": "Node",
      "esModuleInterop": true,
      "outDir": "dist",
      "strict": true,
      "sourceMap": true,
      "resolveJsonModule": true,
      "baseUrl": ".",
      "paths": {
        "*": ["src/*"]
      }
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules"]
  }

package.json

{
  "name": "fumanchu-fiddle",
  "version": "1.0.0",
  "main": "dist/index.js",
  "license": "MIT",
  "type": "module",
  "types": "dist/index.d.ts",
  "devDependencies": {
    "@types/node": "^18.0.0",
    "typescript": "^4.5.4"
  },
  "dependencies": {
    "@jaredwray/fumanchu": "^1.3.0"
  }
}
jaredwray commented 4 months ago

@francescosalvi - we are already doing the handlebars.create()for you so it is sending back the instance of handlebars with all of the helpers included in it. Here is an example of how to use the code:

import handlebars from '@jaredwray/fumanchu';
const template = handlebars.compile('{{#if (eq foo "bar")}}<p>Foo is bar</p>{{/if}}');
const html = template({foo: 'bar'});
console.log(html);

Here is also a reference from a package I maintain called ecto: https://github.com/jaredwray/ecto/blob/main/src/engines/handlebars.ts

francescosalvi commented 4 months ago

I was not asking advice about the intended use of the library, which I do understand; I was pointing out that as it stands, its type declarations seem incorrect.

Take another example: in the readme it's stated

If you only want to use handlebar helpers you can easily do that by doing the following: var helpers = require('@jaredwray/fumanchu').handlebarHelpers;

But this (using ESM) will not compile:

import { handlebarHelpers} from '@jaredwray/fumanchu'; // Module '"@jaredwray/fumanchu"' has no exported member 'handlebarHelpers'.
jaredwray commented 3 months ago

Ah!

Can you try it with the new branch and pull request? #47

francescosalvi commented 3 months ago

@jaredwray I updated the package.json as such:

"devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.4.5"
  },
  "dependencies": {
    "@jaredwray/fumanchu": "jaredwray/fumanchu#main"
  }

but now any import fails with:

node_modules/@jaredwray/fumanchu/index.d.ts:2:26 - error TS2305: Module '"handlebars"' has no exported member 'HandlebarsLib'.

2 import { HelperDelegate, HandlebarsLib as HandlebarsNamespace } from 'handlebars';
                           ~~~~~~~~~~~~~

Found 1 error in node_modules/@jaredwray/fumanchu/index.d.ts:2

(To be 100% sure I even cloned the repo, switched to main, pulled, installed deps, and I get the same report in VSCode as soon as I open index.d.ts)

jaredwray commented 3 months ago

Would this branch work better? https://github.com/jaredwray/fumanchu/tree/types-definition-update

francescosalvi commented 3 months ago

@jaredwray what i did

index.d.ts:1:60 - error TS2305: Module '"handlebars"' has no exported member 'TemplateSpecification'.

1 import { TemplateDelegate, RuntimeOptions, HelperDelegate, TemplateSpecification, compile, registerHelper } from 'handlebars';


index.d.ts:16:30 - error TS2693: 'TemplateDelegate' only refers to a type, but is being used as a value here.

16     TemplateDelegate: typeof TemplateDelegate;

index.d.ts:17:28 - error TS2693: 'RuntimeOptions' only refers to a type, but is being used as a value here.

17 RuntimeOptions: typeof RuntimeOptions;


index.d.ts:18:28 - error TS2693: 'HelperDelegate' only refers to a type, but is being used as a value here.

18     HelperDelegate: typeof HelperDelegate;

index.d.ts:20:20 - error TS2552: Cannot find name 'HandlebarsLib'. Did you mean 'handlebars'?

20 create: typeof HandlebarsLib.create;


  index.d.ts:13:15
    13 declare const handlebars: {
'handlebars' is declared here.

index.d.ts:27:1 - error TS2309: An export assignment cannot be used in a module with other exported elements.

27 export = handlebars;



Found 6 errors in the same file, starting at: index.d.ts:1
```
jaredwray commented 3 months ago

Thanks. Went for a more simple type definition. Let me know if that is working better.

jaredwray commented 3 months ago

its merged into main. FYI