Repository navigation
refactor: keep any out of implementation code - #571
Conversation
Raise no-explicit-any to an error outside tests and move the one allowed `any` into the internal CallerTypedArgs type used by the callback APIs. Reword the principle docs and agent instructions to match. Refs #568
🦋 Changeset detectedLatest commit: c56dd31 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Size Change: +7 B (+0.01%) Total Size: 115 kB 📦 View Changed
ℹ️ View Unchanged
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #571 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 69 70 +1
Lines 2281 2285 +4
Branches 737 738 +1
=========================================
+ Hits 2281 2285 +4 🚀 New features to boost your workflow:
|
| @@ -0,0 +1,7 @@ | |||
| /** | |||
| * Parameter list of a function the caller passes in. | |||
| * The caller's own annotations decide the types, and unannotated parameters end up as `any`. | |||
There was a problem hiding this comment.
One small wording suggestion: could we scope “unannotated parameters end up as any” to the generic callback APIs using CallerTypedArgs, when no other type information is available?
For example, useInputState('', value => value.trim()) infers value as string without an explicit annotation.
Maybe we could say:
Some generic callback APIs use CallerTypedArgs to preserve compatibility. When no annotations or other inference context are available, callback parameters may fall back to any.
There was a problem hiding this comment.
Thanks 👍
useInputState takes a fixed (value: string) => string type, so it does not use CallerTypedArgs
but i think you are right the wording was too strong
so I updated 96f1bb5
There was a problem hiding this comment.
Thanks for the clarification and the quick update! Looks good to me. 👍
Callback parameters take their types from annotations or the inference context, not from annotations alone, and fixed-type callbacks such as useInputState's never fall back to `any`.
mnxmnz
left a comment
There was a problem hiding this comment.
Thanks for working on this!
It looks like consumer builds fail with TS2742. Could you take a look?
The emitted return type of useThrottle now references CallerTypedArgs from dist/_internal/types.mjs, but that path isn't exported, so packages that emit declarations seem to break.
// consumer, declaration: true
export function useScrollHandler() {
return useThrottle((y: number) => console.log(y), 16);
}
// TS2742 ... cannot be named without a reference to '.../dist/_internal/types.mjs'(It doesn't show up in this repo's workspaces, because they link to the local package. It shows up when the package is installed from npm.)
Thanks in advance!
A consumer that emits declarations got TS2742 when it exported their result: useThrottle's inferred type named CallerTypedArgs and useDebounce's named DebouncedFunction, and the package entry exports neither. The verify-pack consumer fixture now emits declarations and covers both. useThrottle's returned function now takes the callback's parameters instead of any[].
Overview
Refs #568
The principles said "No
anyTypes", but five callback files disabledno-explicit-anyfor the whole file and the rule was only a warning, soanycould slip into implementation code unnoticed. The callback APIs do needany[]for their parameter list:unknown[]rejects annotated callbacks because function parameters are compared contravariantly.This PR keeps the callback types as they are and makes the policy explicit:
no-explicit-anyis now an error. Tests and_internal/test-utilskeep it as a warning.anylives inCallerTypedArgs(src/_internal/types.ts).usePreservedCallback,useDebounce,useThrottle,useCallbackOncePerRenderand the internaldebounce/throttleuse it, and their file-wide disables are gone.anys inuseStorageState's internal helpers are nowunknown, with the same type behavior.design-principles.md(all locales), C4 ofhook-design-principles.md(en, ko) and the agent instruction files describe the new rule.Public type changes, covered by a minor changeset:
useThrottlenow returns a function that takes the callback's parameters instead ofany[], so a call with arguments the callback does not take is a type error.useThrottleanduseDebouncewrite out their return types, so a consumer that emits declarations can export their result without TS2742.useDebouncealready failed this way in 0.3.3. The verify-pack consumer fixture now emits declarations and covers both.Known limitation: passing an
any-typed callback tousePreservedCallbackmakes its inferred type nameCallerTypedArgs, which still fails with TS2742 in a consumer that emits declarations. Fixing it would mean exporting the internalanyalias, so it is left as is.Checklist
yarn run fixto format and lint the code and docs?yarn run test:coverageto make sure there is no uncovered line?useThrottle's@template)