Skip to content

Commit 721287a

Browse files
committed
fix(types): keep prop-types out of the generated public declarations
tsc was inferring the static propTypes objects as PropTypes.Requireable<...>, which emitted `import PropTypes from 'prop-types'` into the shipped .d.ts and forced consumers to install @types/prop-types — a type dependency the v4.5.0 hand-written typings never had. Annotate both classes' propTypes as {[key: string]: unknown} so the inferred PropTypes types stay out of the declarations. (DraggableCore had this annotation originally; it was dropped in an earlier cleanup, and Draggable never had it.) Add a Contract 3 to scripts/verify-build.cjs that fails the build if any emitted .d.ts references 'prop-types' — the type-compat test compiles against source (where prop-types resolves) so it cannot catch a consumer-facing leak; this guard inspects the actual artifacts. Verified by installing the packed tarball into a clean project with no @types/prop-types and typechecking a consumer under both bundler and node16 resolution.
1 parent 0e32702 commit 721287a

3 files changed

Lines changed: 33 additions & 3 deletions

File tree

lib/Draggable.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@ class Draggable extends React.Component<Partial<DraggableProps>, DraggableState>
5151

5252
static displayName?: string = 'Draggable';
5353

54-
static propTypes = {
54+
// The index-signature annotation is load-bearing: without it tsc infers the
55+
// PropTypes.Requireable<...> types and emits `import PropTypes from 'prop-types'`
56+
// into the generated public .d.ts, forcing consumers to install
57+
// @types/prop-types (the v4.5.0 hand-written typings had no prop-types dep).
58+
// Do not remove. See lib/DraggableCore.tsx for the same guard.
59+
static propTypes: {[key: string]: unknown} = {
5560
// Accepts all props <DraggableCore> accepts.
5661
...DraggableCore.propTypes,
5762

lib/DraggableCore.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ export default class DraggableCore extends React.Component<Partial<DraggableCore
7373

7474
static displayName: string | undefined = 'DraggableCore';
7575

76-
static propTypes = {
76+
// The index-signature annotation is load-bearing: without it tsc infers the
77+
// PropTypes.Requireable<...> types and emits `import PropTypes from 'prop-types'`
78+
// into the generated public .d.ts, forcing consumers to install
79+
// @types/prop-types (the v4.5.0 hand-written typings had no prop-types dep).
80+
// Do not remove. See lib/Draggable.tsx for the same guard.
81+
static propTypes: {[key: string]: unknown} = {
7782
/**
7883
* `allowAnyClick` allows dragging using any mouse button.
7984
* By default, we only accept the left button.

scripts/verify-build.cjs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ assert.ok(
5656
'UMD bundle must expose the global `ReactDraggable`'
5757
);
5858

59+
// ── Contract 3: generated declarations must not leak internal-only deps ──────
60+
// The shipped .d.ts is generated from source. The v4.5.0 hand-written typings
61+
// depended only on `react`; if a `propTypes`/`defaultProps` static loses its
62+
// index-signature annotation, tsc infers PropTypes.* types and emits
63+
// `import ... 'prop-types'` into the public declaration, silently forcing
64+
// consumers to install @types/prop-types. Fail the build if that creeps back.
65+
const dtsDir = path.join(root, 'build', 'cjs');
66+
const dtsFiles = fs
67+
.readdirSync(dtsDir)
68+
.filter((f) => f.endsWith('.d.ts') || f.endsWith('.d.mts'));
69+
const leaks = dtsFiles.filter((f) =>
70+
/['"]prop-types['"]/.test(fs.readFileSync(path.join(dtsDir, f), 'utf8'))
71+
);
72+
assert.equal(
73+
leaks.length,
74+
0,
75+
`Generated declarations leak 'prop-types' (consumers would need @types/prop-types): ${leaks.join(', ')}. ` +
76+
`Annotate the offending static (e.g. \`static propTypes: {[key: string]: unknown}\`) so tsc does not emit PropTypes types.`
77+
);
78+
5979
console.log(
60-
'✓ build contract OK: CJS module.exports===Draggable (+.default, .DraggableCore); UMD global ReactDraggable'
80+
'✓ build contract OK: CJS module.exports===Draggable (+.default, .DraggableCore); UMD global ReactDraggable; no prop-types leak in .d.ts'
6181
);

0 commit comments

Comments
 (0)