[2.0 rc.15 / next] Types: `data-*` attributes are rejected in props objects typed with `ComponentProps` / `JSX.HTMLAttributes`
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- Nửa ngày
- Mức phù hợp với người mới
- 45/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
- Lĩnh vực
- frontend
Hướng nghiên cứu
Start with the JSX type declarations in packages/web (the DOM attribute interfaces and the ElementAttributes base), and reproduce with the three errors in the gist, using tsc -p .. The fix is a template-literal index signature for data-${string} keys on the base attribute interface. Done when the three errors disappear, the @ts-expect-error checks still fail for non-data keys and non-primitive data values, and the type tests pass. Because this touches public types, confirm the approach with a maintainer first.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
In JSX, data-* attributes are accepted on intrinsic elements. In an object typed with the same element's props (ComponentProps<"div">, JSX.HTMLAttributes<T>), they are rejected. That type is the natural one for a function that returns props to spread onto an element. This request is to declare data-* keys in the DOM attribute types with a template-literal index signature.
Reproduction
import type { ComponentProps, JSX } from "@solidjs/web";
// In JSX, data-* attributes are accepted on intrinsic elements:
export const ok = <div data-state="open" />;
// ...but not in an object typed with the same element's props:
export const a: JSX.HTMLAttributes<HTMLDivElement> = { "data-state": "open" };
export const b: ComponentProps<"div"> = { role: "button", "data-state": "open" };
// ...nor when a function returning those props is spread back onto the element:
function disclosure(): ComponentProps<"button"> {
return { "aria-expanded": "false", "data-state": "closed" };
}
export const c = <button {...disclosure()} />;
tsc -p . (TypeScript 5.9.3 and 7.0.2 give the same errors) with "jsx": "preserve", "jsxImportSource": "@solidjs/web", "strict": true:
data-attrs.tsx(7,56): error TS2353: Object literal may only specify known properties, and '"data-state"' does not exist in type 'HTMLAttributes<HTMLDivElement>'.
data-attrs.tsx(8,59): error TS2353: Object literal may only specify known properties, and '"data-state"' does not exist in type 'HTMLAttributes<HTMLDivElement> & Properties<HTMLDivElement>'.
data-attrs.tsx(12,38): error TS2353: Object literal may only specify known properties, and '"data-state"' does not exist in type 'ButtonHTMLAttributes<HTMLButtonElement> & Properties<HTMLButtonElement>'.
TypeScript exempts hyphenated names from attribute checks only in JSX syntax, so the object forms fail.
Proposal
Add a template-literal index signature to the base attribute interface in @solidjs/web's JSX types. I tested this module augmentation against rc.15:
import "@solidjs/web";
declare module "@solidjs/web" {
namespace JSX {
interface ElementAttributes<T> {
[attr: `data-${string}`]: string | number | boolean | undefined;
}
}
}
With it, the three errors above go away, and these still hold:
type P = Omit<ComponentProps<"div">, "ref">;
export const p: P = { "data-x": "1", class: "a" };
// @ts-expect-error unknown non-data keys are still rejected
export const q: P = { foo: 1 };
// @ts-expect-error data values stay primitive
export const r: P = { "data-x": {} };
export const s = <div data-n={1} data-b={true} />;
React's DOM types have the same gap, so this is not a regression. Solid 2 is already rewriting the attribute types (lowercase names, RemoveAttribute), so this seems a good point to close it.
Why it matters
Headless component libraries expose state as data-* attributes (data-state, data-disabled, data-highlighted) and compose behaviour as functions that return props objects, which are merged and spread onto parts. Without the index signature, each such function has to widen its return type or cast. Until this lands, the augmentation above is the workaround.
Versions
@solidjs/web/solid-js2.0.0-rc.15. Onnextat eb4e019,packages/webdeclares nodata-*key.- TypeScript 5.9.3 and 7.0.2
Runnable repro: https://gist.github.com/cevr/e421f9dbfe6c0da2e92818647dd408f0 (bun install && bun run repro)
Filed with Claude Code on behalf of @cevr.
- Ngôn ngữ chính
- TypeScript
- Star
- 36.1k
- Fork
- 1.1k
- Merge trung bình
- 11 giờ 37 phút
- Pull request đã merge (30 ngày)
- 344
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của solidjs/solid
-
`lazy()`: remounting an already-loaded component renders empty (or the Suspense fallback) since 1.9.14Có thể đã có người làm @itisrmk đã nhận 3 ngày trước. Đang mở1.x
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[2.0 rc.15 + next] For row lifecycle cleanup inherits the list computation and halts on a shared-state writeCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 51/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 1-2 ngày Mức phù hợp với người mới 48/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
`createRoot`'s dispose function keeps `fn` alive, so `<For>`/`<Index>` rows retain removed list itemsCó thể đã có người làm @boombang đã nhận 5 ngày trước. Đang mở1.x
Độ khó 4/5 1-2 ngày Mức phù hợp với người mới 45/100
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của solidjs/solid
Issue tương tự
-
Sequências em espanhol: «Atualizado em», a aba «Fila» e o valor 'pause' ainda saem em portuguêsĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
melgarafael/DeskcommCRM#3104 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
🐛 [Bug] Mobile: on the login and registration pages the footer sits below the visible screenĐang mởbug service: webapp
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Ocelot-Social-Community/Ocelot-Social#10684 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
nicobailon/pi-subagents#2978 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
getsentry/sentry-conventions#732 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày