能否通过TypeScript或ESLint实现React组件宽度属性的精准格式校验?
I’ve dealt with exactly this kind of type validation challenge while upgrading a React + TypeScript Design System to support CSS-in-JS and scale-based sizing. The good news is TypeScript’s advanced type system lets us build a solution that’s strict enough to block invalid pure-numeric strings, but flexible enough to support all your valid use cases. Here’s how to make it work:
We need a custom type that:
- Accepts numeric values (for your design system’s scale, e.g.,
width={8}) - Accepts string values with units (like
"125px"or"10%") or global CSS keywords (like"inherit"or"auto") - Rejects pure numeric strings (e.g.,
"8") - Leaves other properties (like
line-heightorfont-weight) untouched since they have their own valid type requirements
1. Target Pure Numeric Strings
First, create a type that matches any string composed entirely of numbers (including decimals) using TypeScript’s template string feature:
// Matches strings like "8", "123.45", "0" — all pure numeric values as strings type NumericString = `${number}`;
2. Build a Valid Length Type
Next, define a type that allows numbers OR strings that aren’t pure numeric strings:
// Allow numeric scale values + strings with units/keywords (exclude pure numeric strings) type ValidLength = number | Exclude<string, NumericString>;
3. Update the Width Type
Replace your existing Width type with this revised version, keeping all your existing CSS keyword values:
// Define global CSS keywords if you haven’t already type Globals = "inherit" | "initial" | "unset" | "revert"; export type Width = | Globals | ValidLength | "-moz-fit-content" | "-moz-max-content" | "-moz-min-content" | "-webkit-fit-content" | "-webkit-max-content" | "auto" | "fit-content" | "intrinsic" | "max-content" | "min-content" | "min-intrinsic";
4. (Optional) Enforce Your Size Scale
If you want to restrict numeric values to your predefined design system scale (e.g., only 0, 4, 8, 12...), swap the number type with your specific scale union:
// Your design system’s approved size scale values type SizeScale = 0 | 4 | 8 | 12 | 16 | 20 | 24 | 32 | 40 | 48; // Update ValidLength to use the scale instead of any number type ValidLength = SizeScale | Exclude<string, NumericString>;
This adds a second layer of validation: width={30} will throw an error because 30 isn’t in your scale, and width="30" will fail because it’s a pure numeric string. Perfect for enforcing your design system rules!
Here’s how different usage scenarios will behave:
- ✅ Valid inputs (no TypeScript errors):
<MyComponent width={8} />(numeric scale value)<MyComponent width="125px" />(string with unit)<MyComponent width="inherit" />(global CSS keyword)<MyComponent width="fit-content" />(CSS sizing keyword)
- ❌ Invalid inputs (TypeScript will flag these):
<MyComponent width="8" />(pure numeric string)<MyComponent width={30} />(only when using the SizeScale restriction)
Since we’re only modifying the Width type, properties like line-height or font-weight that need to accept pure numeric strings can retain their original type definitions:
// Example: line-height allows numbers or any string (including pure numeric ones) export type LineHeight = number | string;
内容的提问来源于stack exchange,提问作者Laurent Jouanneau Dario

