Skip to content

CJS types missing: require condition has no .d.cts, so TypeScript CommonJS consumers get TS1479 despite the CJS bundle existing #1811

Description

@felipernb

Summary

@google/genai ships a working CommonJS bundle (added in #605, v1.1.0), but the exports map declares one types entry shared by both the import and require conditions. Because package.json sets "type": "module", TypeScript treats that .d.ts as an ES module, so a CommonJS consumer is told the package cannot be require()d — even though require() resolves to a real .cjs file and works perfectly at runtime.

This is the type-level half of #605 that never landed. It's also, I believe, the actual root cause of #648, which was closed with a "set type: module" workaround rather than a fix — that thread has a second user asking how to solve it and the original reporter ending with "I switched to this one package" (openai-node). So this is quietly costing you TypeScript CJS users.

Environment

  • @google/genai 1.52.0
  • typescript 6.0.3 (also reproduces on 5.x)
  • Node 22.22.2
  • Consumer is CommonJS (no "type": "module"), module/moduleResolution: node16 (same on nodenext)

Minimal reproduction

package.json

{ "name": "genai-cjs-repro", "version": "1.0.0", "private": true }

tsconfig.json

{
  "compilerOptions": {
    "module": "node16",
    "moduleResolution": "node16",
    "target": "es2022",
    "strict": true,
    "noEmit": true
  },
  "include": ["src"]
}

src/index.ts

import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({ apiKey: 'x' });
npm i @google/genai@1.52.0 typescript@6.0.3
npx tsc -p tsconfig.json

Actual

src/index.ts(1,29): error TS1479: The current file is a CommonJS module whose imports will
produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be
imported with 'require'. Consider writing a dynamic 'import("@google/genai")' call instead.

Type-only imports fail too, with:

error TS1541: Type-only import of an ECMAScript module from a CommonJS module must have a
'resolution-mode' attribute.

But the runtime is fine

In that same project, require() resolves to the CJS bundle and instantiates correctly:

$ node -e "const p=require.resolve('@google/genai'); const {GoogleGenAI}=require('@google/genai');
           console.log(p.split('/node_modules/')[1], typeof GoogleGenAI, typeof new GoogleGenAI({apiKey:'x'}))"
@google/genai/dist/node/index.cjs function object

So this is purely a types-packaging gap, not a runtime incompatibility. Nothing here relies on Node's require(esm) support.

Cause

dist/node/ contains index.mjs, index.cjs, and only node.d.ts — there is no node.d.cts. The current condition:

"node": {
  "types": "./dist/node/node.d.ts",
  "import": "./dist/node/index.mjs",
  "require": "./dist/node/index.cjs",
  "default": "./dist/node/index.mjs"
}

With "type": "module" at the package root, node.d.ts is an ESM declaration file, and TypeScript has no CJS type view to pair with the require target.

Suggested fix

Emit a CJS declaration file and select types per condition, so each resolves to a declaration whose module kind matches its target:

"node": {
  "import": {
    "types": "./dist/node/node.d.ts",
    "default": "./dist/node/index.mjs"
  },
  "require": {
    "types": "./dist/node/node.d.cts",
    "default": "./dist/node/index.cjs"
  }
}

(Same treatment for the root . entry, which has the identical shape.) This is the standard dual-publish layout and would make TS1479/TS1541 disappear for CJS consumers with no change on the ESM side and no API change.

Workarounds today, for anyone hitting this

  • Type-only imports work with an explicit resolution mode:
    import type { GoogleGenAI } from '@google/genai' with { 'resolution-mode': 'import' };
  • A value import needs await import('@google/genai'), which forces the acquiring function to be async — awkward when the client is built in a constructor or property initializer, as it can't be awaited there.

Metadata

Metadata

Assignees

Labels

api:gemini-apipriority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions