Repository navigation
[전수조사/J] 타입·ESLint 정합성 #684
Copy link
Copy link
Open
Labels
bugSomething isn't workingSomething isn't working
Description
타입과 lint가 빌드의 실제 동작과 다른 문제들입니다. 확인 예: data-values={[5,5]}처럼 스타일이 아닌 prop의 배열까지 lint autofix가 고침.
전체 계획과 결정 사항은 추적 이슈(#682)에 있습니다. 조사 기준 커밋: 77daad74 (현재 main d0b84255).
결정에 따른 작업
- (필수) css-utils-literal-only 오탐: 함수 안에 선언한
const fade = keyframes(...)(KNOWN-14) - (권장) "
Xis read at runtime" 빌드 에러를 미리 알리는 lint 규칙(KNOWN-15, TOOL-05)
발견 항목
심각도: P0 = 흔한 사용에서 조용히 틀리거나 크래시, P1 = 흔한 패턴이 명시적 에러로 막히거나 드물게 조용히 틀림, P2 = 드문 경우·도구/문서 불일치, P3 = 있으면 좋음.
필수 (2)
- TOOL-01 (P1, WRONG) Array rules autofix arbitrary non-style data
- 근거:
unrelated-arrays.jsx: lint reports all three array rules underdata-config;probe.tsleaves the data untouched.verifyAndFixchanges{values:[1]},{values:[1,1]},{values:[1,null]}to{values:1}. Source context is any descendant of a tracked component/call (no-duplicate-value/index.ts:71-105,no-useless-responsive/index.ts:64-114,no-useless-tailing-nulls/i… - 수정 방향: Share an extractor-aware style-path classifier; never report/fix arrays beneath pass-through/native/
propsdata unless the owning key is a style prop/selector.
- 근거:
- TOOL-02 (P1, WRONG) Typography/media fixers rewrite arbitrary data
- 근거:
unrelated-properties.jsx: lint rewrites nested data{typography:'$heading'}toheadingand{'@media print':...}to{_print:...}; build leaves both objects unchanged. Implementations recursively match property names inside broad tracked contexts (no-typography-token-prefix/index.ts:54-95,prefer-media-shorthand/index.ts:82-138). - 수정 방향: Gate reports/fixes on a shared style-object ancestry classifier; add pass-through-data regression tests.
- 근거:
권장 (18)
- FN-01 (P1, MISMATCH) Public
css()types reject extractor-supported composition- 근거:
packages/react/src/utils/css.ts:3-9declares only zero/one-argument overloads, whilecss-forms.tsxsuccessfully compilescss('external-class', base, ...extra, {p:3})to a composed class string - 수정 방향: add typed rest-argument overloads covering classes, style objects, arrays and conditional falsy values; type later-rule precedence consistently
- 근거:
- FN-02 (P1, MISMATCH) Tagged-template declarations omit supported interpolations
- 근거:
css.ts:4,global-css.ts:90, andkeyframes.ts:11accept onlyTemplateStringsArray;templates-static.tsxsuccessfully evaluates${n * 4},${n}, and keyframe interpolations - 수정 방향: add
...valuesoverloads matching build-supported static/style-result inputs; keep runtime-only values rejected by extraction
- 근거:
- SC-16 (P1, MISMATCH) Ambient styled-components types omit major v6 surface and break DefaultTheme augmentation
- 근거:
compat/styled-components.d.ts:1-18declares onlycss,keyframes, DefaultTheme alias, seven compat values, and styled. It omitsThemeConsumer,createTheme,CSSProperties,CSSObject,CSSPseudos,CSSKeyframes,CSSProp, ServerStyleSheet/manager option contracts, and other public types. It exportsStyledTheme as DefaultThemeas a type alias, whereas SC exposes… - 수정 방향: Model the public v6 type surface in the compat declaration, declare
interface DefaultTheme, and type styled/attrs/config/runtime helpers against it.
- 근거:
- TOOL-03 (P1, MISMATCH) Six rules ignore build-supported import aliases
- 근거:
ImportStoragerecords only@devup-ui/react(packages/eslint-plugin/src/utils/import-storage.ts:26-27). Emotion/styled-components cases compile through default aliases but receive none of the duplicate/responsive/tailing/typography/media/styleOrder diagnostics (emotion-static-rules.jsx,styled-components-static-rules.jsx). - 수정 방향: Centralize alias/API recognition with plugin-utils defaults plus configurable aliases; distinguish each absorbed library's semantics (especially Vanilla Extract composition arrays).
- 근거:
- TOOL-04 (P1, MISMATCH) Literal-only rule misses aliased Emotion/styled-components and
.css.ts- 근거: dynamic Emotion/styled-components calls get no lint message while build errors (
emotion-dynamic.jsx,styled-components-dynamic.jsx).vanilla-dynamic.css.tsgets no lint message while Boa crashesReferenceError: window is not defined. StyleX is the sole compat family recognized directly (css-utils-literal-only/index.ts:978-1021). - 수정 방향: Recognize enabled aliases and add a TypeScript parser/config for
.css.ts; model Vanilla Extract's evaluator separately from Devup object styles.
- 근거: dynamic Emotion/styled-components calls get no lint message while build errors (
- TOOL-05 (P1, MISMATCH) KNOWN-15 and bare styled reads have no lint rule
- 근거:
known15-runtime-read.jsx(export const runtime=css) andstyled-without-styles.jsx(styled.div) have no lint messages; build errors “is read at runtime, where it does not exist.” - 수정 방향: Add a no-runtime-read rule using import references, allowing only extractor-supported call/tag/member/render positions; include namespace/default/destructuring/re-export cases.
- 근거:
- TOOL-09 (P1, MISMATCH) Main types admit build-time-invalid dynamic/runtime usage
- 근거: TS 7 compiles every line in
types/unsound.tsx, including dynamiccss/globalCss/keyframes,runtimeRead=css, barestyled.div, bad typography/tokens and invalidstyleOrder; probes produce explicit errors for the first five categories. - 수정 방향: Keep ergonomic value types, but cover syntactic/static constraints with the missing ESLint rules and parser support; tighten literal unions where generated theme data permits.
- 근거: TS 7 compiles every line in
- TOOL-11 (P1, MISMATCH) Custom shorthand config has no complete generated responsive typing
- 근거: plugin options expose
shorthands?: CustomShorthands(packages/plugin-utils/src/shared.ts:96-108), but theme generation receives only five interface names (shared.ts:71-90) and no shorthand interface. ManualDevupCustomShorthandsaugmentation accepts scalar/selector usage buttypes/custom-shorthand.tsxrejects[1,null,2], although build style props are responsive by… - 수정 방향: Generate
DevupCustomShorthandsentries as optionalResponsiveValue-compatible property types and add TS 7 fixtures driven by plugin shorthand config.
- 근거: plugin options expose
- TOOL-13 (P1, MISMATCH) Emotion/styled-components result types are collapsed to
string- 근거: compat declarations re-export Devup
css/keyframes, sotypes/compat.tsxaccepts assignments tostring. Official Emotion returnsSerializedStyles/Keyframes; styled-components returns composableRuleSet/Keyframes. - 수정 방향: Declare compat-specific opaque result interfaces and accepted composition positions while mapping them to build placeholders internally.
- 근거: compat declarations re-export Devup
- TOOL-14 (P1, ERR-gap) Styled compat omits
.attrsand generic global styles- 근거:
styled.button.attrs(...)andcreateGlobalStyle<Props>fail in bothtypes/supported.tsxandtypes/compat.tsx; sourcestyled.ts:8-47has no attrs surface andcreate-global-style.ts:10-22has no prop generic. Dynamic global interpolation also gets no lint warning and build errors. - 수정 방향: Either implement static attrs and explicitly document unsupported dynamic globals, or narrow the compatibility claim; add declarations only with corresponding extractor behavior.
- 근거:
- TOOL-15 (P1, MISMATCH) ThemeProvider compat rejects official outer-theme functions
- 근거: both Emotion and styled-components
<ThemeProvider theme={outer => ...}>fail intypes/compat.tsx; declaration resolves toStyledTheme, not object-or-function. Runtime compat exports one provider (compat/index.ts:10-20). - 수정 방향: Implement deterministic outer-theme factory evaluation or document/reject the compatibility feature at migration time; align both ambient modules and runtime prop type.
- 근거: both Emotion and styled-components
- TOOL-16 (P1, MISMATCH) Vanilla Extract
stylecomposition is mistyped- 근거:
types/compat.tsxrejectsstyle([{color:'red'},{padding:4}]);vanilla-array.css.tsbuilds to two classes ("a b"). Official signature acceptsComplexStyleRule[]: https://vanilla-extract.style/documentation/api/style/. - 수정 방향: Add the array overload and preserve recursive contract/tuple inference for
createTheme,assignVars, vars and font overloads.
- 근거:
- JSX-13 (P2, MISMATCH) Custom shorthand targets accept arbitrary misspelled CSS names
- 근거:
CustomShorthands = Record<string, readonly string[]>has no target-name constraint (packages/plugin-utils/src/types.ts:55-56), and WASM deserializes directly toBTreeMap<String, Vec<String>>before registration (bindings/devup-ui-wasm/src/lib.rs:612-623). - 수정 방향: validate and normalize targets during plugin setup; report the shorthand and bad target before extraction. Type targets against the canonical property-name union where practical.
- 근거:
- PLG-25 (P2, MISMATCH) Public theme type spells the documented
shadowfield incorrectly- 근거:
DevupThemedefinesshadows?: ThemeShadows(plugin-utils/types.ts:48-53), while rootREADME.mdanddevup.jsonschema examples usetheme.shadow. This makes correct configs fail type guidance and accepts a field the engine docs do not consume. - 수정 방향: Rename to
shadow(with a deliberate compatibility alias only if public consumers used the erroneous type) and add a type-level fixture.
- 근거:
- TOOL-10 (P2, MISMATCH) Generated theme typing constrains typography/theme names but not
$tokens- 근거:
types/theme-errors.tsxrejects unknown/prefixed typography and_themeUnknown, but unknown$missingcolor/length/shadow tokens compile. Generated shape is a root augmentation withCustomColors,DevupThemeTypography,CustomLength,CustomShadows,DevupTheme(apps/vite-lib/df/theme.d.ts:1). - 수정 방향: Add branded/template token branches keyed by generated interfaces without narrowing normal CSS values; consider a dedicated token helper when CSS
stringprevents exclusion.
- 근거:
- TOOL-12 (P2, MISMATCH)
styleVarsrejects numeric values supported by build- 근거:
styleVars?: Record<string,string|undefined>(props/index.ts:43-48) rejects--count:1;style-vars-number.jsxbuilds tostyle={{"--count":1}}and validcolor:var(--count). - 수정 방향: Widen values to
string | number | undefinedand add type/extractor tests.
- 근거:
- VE-06 (P2, MISMATCH) compatibility declarations do not match the evaluator
- 근거:
packages/react/src/compat/vanilla-extract.d.ts:1-38declares unregisteredglobalKeyframes/composeStyles/generateIdentifier, omits implementedcreateGlobalThemeContract, and omits the implemented secondstyleVariantsmapper argument (libs/extractor/src/vanilla_extract.rs:736-760,985-1020). - 수정 방향: Generate or hand-maintain declarations from the registered API table; add type tests for every overload.
- 근거:
- JSX-14 (P3, MAINT) Polymorphic component declarations duplicate the default overload
- 근거: each of
packages/react/src/components/{Box,Flex,Grid,Center,VStack,Text,Button,Input,Image}.tsxrepeats an implementation-shaped default-props overload before the generic overload and implementation; e.g.Box.tsx:6-20. - 수정 방향: remove the duplicate default signature from all nine compile-time component declarations and retain type tests for both default and polymorphic use.
- 근거: each of
선택 (4)
- TOOL-07 (P2, WRONG)
styleOrderstring parsing accepts junk- 근거:
style-order.jsx: lint does not reportstyleOrder="100px"because source usesparseInt(style-order-range/index.ts:24-28,56-64); build silently places the rule at order 100. README says the prop must be a number in 1..254. - 수정 방향: Validate the complete trimmed string with an integer regex/
Number, notparseInt; add junk-suffix tests.
- 근거:
- TOOL-08 (P2, MAINT) Rule documentation/package entry is incomplete and inaccurate
- 근거:
packages/eslint-plugin/README.mdis empty.style-order-range/README.md:7-47uses bare<div>, but implementation only checks recognized Devup components/utilities; recommended config behavior exists only in source/snapshot. - 수정 방향: Populate package README and correct per-rule examples; state
.css.tsand compat behavior explicitly.
- 근거:
- TOOL-17 (P2, MISMATCH) StyleX compat surface/types are incomplete
- 근거: runtime/type files expose a hand-written shallow
StylePropertiessubset (utils/stylex.ts:1-91,compat/stylex.d.ts:1-21), not opaqueStyleXStylesor nested typed variable contracts; officialwhen/envsurface is absent. - 수정 방향: Inventory the supported native extractor subset, export compatible opaque types, and either implement or explicitly exclude each missing official API.
- 근거: runtime/type files expose a hand-written shallow
- TOOL-18 (P2, TEST) Raw TS 7 source checking depends on
skipLibCheck- 근거: isolated TS 7 with
skipLibCheck:falsereports multiple circular aliases and missing names (TFeatureType,TPageMarginBoxType) in installedcsstype-extra@0.1.36; withskipLibCheck:true, accepted and unsound fixtures compile cleanly. - 수정 방향: Upgrade/fix
csstype-extrafor TS 7 and add a strict consumer typecheck withoutskipLibCheckwhen dependency compatibility permits.
- 근거: isolated TS 7 with
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
fix(eslint-plugin): check only the values the build reads as styles (#…
fix(eslint-plugin): write the changepack without a BOM
docs(eslint-plugin): document the rules and what counts as a style
fix(react): align StyleX and supported CSS property contracts
fix(extractor): enforce the shared static styleOrder contract
fix(config): validate custom shorthand targets atomically
fix(plugins): validate shorthand options before plugin setup
fix(extractor): validate order metadata in composed css props
fix(extractor): honor styleOrder across style APIs
test(extractor): avoid redundant parser nesting in whole-file probes
fix(extractor): preserve authored order metadata and forwarding
test(extractor): serialize every fallback evaluation case
fix(eslint-plugin): check styleOrder only where the build reads it (#733
fix(packages): restore main release baseline in types and lint stack
14 remaining items
test(extractor): make scalar style expectations typed and total
test(extractor): cover source-fed literal mixin metadata diagnostics
test(extractor): cover ClassNames finite logical selection and nested…
test(extractor): cover saved finite style choice and array lookup
test(extractor): cover the captured static member class leaf
test(extractor): cover styled tag fallback, attrs restoration and mix…
test(extractor): cover ClassNames logical, finite, array and captured…
test(extractor): cover spread-literal styled fallback, normalised typ…
test(extractor): cover imported finite producers, normalised metadata…
refactor(extractor): remove styled, class-names and constant branches…
refactor(extractor): split shared classifiers and cover prefix, boole…
refactor(extractor): give ClassNames source classes their own Call-fr…
refactor(extractor): cover finite union, literal spread and remove th…
refactor(extractor): split the finite emitter reader into one helper …
refactor(extractor): drop jsx_expression_to_style_order now that only…