Skip to content

chore: harden TypeScript types across codebase#7

Merged
crippledgeek merged 9 commits into
masterfrom
chore/type-hardening
Mar 4, 2026
Merged

chore: harden TypeScript types across codebase#7
crippledgeek merged 9 commits into
masterfrom
chore/type-hardening

Conversation

@crippledgeek
Copy link
Copy Markdown
Owner

@crippledgeek crippledgeek commented Mar 4, 2026

Summary

  • ErrorCode literal type with exhaustive never switch in getErrorMessage — compiler catches unhandled error codes
  • StandardSchemaIssue replaces unknown[] for form errors, with path aligned to Standard Schema V1 spec
  • ConverterMode = 'encode' | 'decode' literal union replaces string for mode across all config signatures
  • FieldConfig<T> discriminated unionSelectFieldConfig<T> | TextAreaFieldConfig<T> with name: string & keyof T for compile-time field name validation and never guards for mutual exclusion; placeholder/className only on TextAreaFieldConfig
  • ConverterConfig.schema: ZodType<T, ZodTypeDef, T> — pins both Output and Input types, preventing transform schemas from silently satisfying the constraint

Test plan

  • npm run build passes (zero type errors)
  • npm run lint passes (zero warnings)
  • Zero as any or as unknown as casts introduced
  • All 4 converter configs compile with tightened types
  • QA verified all 11 checklist items
  • Zero runtime behavior changes

Extract ErrorCode from ERROR_CODES const, narrow EncodingError.code
from string to ErrorCode, add never-typed exhaustive default in
getErrorMessage, and add missing cases for ENCODE_FAILED, EMPTY_INPUT,
INPUT_TOO_LARGE.
…rrors

Tighten formatFieldErrors, FieldMetaLike.errors, and FieldErrorMessage
meta.errors from unknown[] to StandardSchemaIssue[], removing the
unsafe cast in formatFieldErrors.
…union

Define ConverterMode = 'encode' | 'decode', update ConverterFormBase,
FieldConfig callbacks, and ConverterConfig function signatures. Update
ConverterPage to use ConverterMode annotation on useStore result.
Split FieldConfig into SelectFieldConfig and TextAreaFieldConfig extending
a shared FieldConfigBase. Use `string & keyof T` for field names. Update
ConverterPage to narrow via field.type before accessing type-specific props.
Link schema output type to the config's generic T parameter so mismatched
schemas produce a compile error. ZodEffects (from superRefine) extends
ZodType, so all 4 converter schemas satisfy the constraint.
…assName, never guards

Move placeholder and className up to FieldConfigBase so both select and
textarea variants share them. Add rows?: never on SelectFieldConfig and
options?: never on TextAreaFieldConfig as mutual exclusion guards.
@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 4, 2026

Deploy Preview for devkit-app ready!

Name Link
🔨 Latest commit c64aee8
🔍 Latest deploy log https://app.netlify.com/projects/devkit-app/deploys/69a84a0aff4f0000085e3242
😎 Deploy Preview https://deploy-preview-7--devkit-app.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@crippledgeek
Copy link
Copy Markdown
Owner Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

- Move placeholder/className from FieldConfigBase to TextAreaFieldConfig
  (selects never use these — adding them was silently ignored)
- Add placeholder?: never and className?: never to SelectFieldConfig
  for compile-time enforcement
- Narrow conditionalInputValidation mode param from string to literal union
- Use shared modeSchema in urlEncoderSchema instead of inline z.enum
@crippledgeek
Copy link
Copy Markdown
Owner Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

- Align StandardSchemaIssue.path with Standard Schema V1 spec
  (ReadonlyArray<PropertyKey | {key: PropertyKey}> instead of (string | number)[])
- Pin ZodType Input parameter: ZodType<T, ZodTypeDef, T> prevents
  transform schemas from silently satisfying the constraint
- Collapse EMPTY_INPUT/INPUT_TOO_LARGE switch cases to return
  error.message directly (avoids potential message duplication)
- Add @internal JSDoc to never-typed guard properties explaining
  their role as discriminated-union sentinels
- Add discriminant JSDoc to type: 'select' and type: 'textarea'
- Clarify ConverterPage comment to describe property resolution intent
@crippledgeek crippledgeek merged commit b788283 into master Mar 4, 2026
6 checks passed
@crippledgeek crippledgeek deleted the chore/type-hardening branch March 4, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant