Skip to content

Published npm package includes raw .ts source files that cause strict-mode type errors in consumers #522

Description

@0xsvrebelo

The published permissionless@0.3.6 npm package includes raw .ts source files (including .test.ts files) alongside the compiled _cjs, _esm, and _types directories. When a consumer project runs tsc --noEmit with strict: true, TypeScript resolves these .ts files and surfaces 19 upstream type errors that exist within the library's own source code.

While the package.json correctly declares "types": "./_types/index.d.ts" and the exports map points to _types/*.d.ts + _esm/*.js + _cjs/*.js, TypeScript still picks up the co-located raw .ts files during type-checking.

Reproduction

1. Create a minimal project:

mkdir permissionless-repro && cd permissionless-repro
npm init -y
npm install permissionless@0.3.6 viem@2.51.3

2. Create tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "esnext",
    "moduleResolution": "bundler",
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "skipLibCheck": false
  },
  "include": ["index.ts"]
}

3. Create index.ts:

import { toSafeSmartAccount } from 'permissionless/accounts';
import { createSmartAccountClient } from 'permissionless';
console.log(toSafeSmartAccount, createSmartAccountClient);

4. Run type-check:

npx tsc --noEmit

Expected Behavior

tsc --noEmit should complete with 0 errors, since the package.json exports map correctly points to pre-compiled .d.ts declarations.

Actual Behavior

19 type errors from within the library's own source files:

node_modules/permissionless/accounts/biconomy/toBiconomySmartAccount.ts(292,25): error TS2322: Type '`0x${string}` | undefined' is not assignable to type '`0x${string}`'.
node_modules/permissionless/accounts/biconomy/toBiconomySmartAccount.ts(293,25): error TS2322: Type 'bigint | undefined' is not assignable to type 'bigint'.
node_modules/permissionless/accounts/safe/signUserOperation.ts(108,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'.
node_modules/permissionless/accounts/safe/toSafeSmartAccount.ts(914,17): error TS2532: Object is possibly 'undefined'.
node_modules/permissionless/accounts/safe/toSafeSmartAccount.ts(915,17): error TS2532: Object is possibly 'undefined'.
... (19 total, spanning biconomy, kernel, light, safe, simple, thirdweb, trust accounts)

Root Cause

The published npm tarball includes raw .ts and .test.ts files at the package root level:

permissionless/
├── accounts/
│   ├── index.ts           ← raw source (should not be published)
│   ├── decodeCalls.test.ts ← test file (should not be published)
│   └── safe/
│       ├── toSafeSmartAccount.ts  ← raw source
│       └── signUserOperation.ts   ← raw source
├── _cjs/    ← compiled (correct)
├── _esm/    ← compiled (correct)
├── _types/  ← declarations (correct)
└── package.json

TypeScript resolves these .ts files during type-checking even when skipLibCheck: false is set, because skipLibCheck only affects .d.ts files — not .ts source files in node_modules.

Suggested Fix

Exclude raw .ts source files from the published npm package by updating the files field in package.json:

{
  "files": [
    "_cjs",
    "_esm",
    "_types",
    "package.json",
    "README.md",
    "LICENSE"
  ]
}

Or add .ts patterns to .npmignore:

# Exclude raw sources — only ship compiled output
*.ts
!*.d.ts
*.test.ts

Workarounds

Consumers can use either of these workarounds:

  1. skipLibCheck: true in tsconfig.json — disables type-checking of all .d.ts (but also suppresses legitimate errors from other libraries)
  2. Filter script — run tsc --noEmit and filter out lines containing permissionless before checking exit code
  3. SWC compiler — use swc for compilation (no type-checking) + filtered tsc for type-checking only

Environment

  • permissionless: 0.3.6
  • viem: 2.51.3
  • typescript: 5.9.3
  • OS: Windows 11 / Node 24
  • Package manager: pnpm 10.33.0

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions