Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

421
Views
¿Por qué se permiten los atributos no estándar de kebab-case mientras que otros no? ¿Y cómo definir tipos como este en TypeScript?

El uso de foo como atributo genera un error:

 // App.tsx // 👇 throws const App = () => <div foo></div> export default App
 Type '{ foo: true; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'. Property 'foo' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.ts(2322)

Pero usar foo-foo está bien, ¿por qué?

 // App.tsx // 👇 no error is thrown const App = () => <div foo-foo></div> export default App

Y lo más importante, ¿cómo definir tipos como este en TypeScript? es decir, solo permitir atributos estándar o de kebab-case.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

La respuesta está en la sección JSX del Manual de mecanografiado :

Si un nombre de atributo no es un identificador JS válido (como un atributo data-* ), no se considera un error si no se encuentra en el tipo de atributos del elemento.

Toda la sección sobre JSX es una lectura muy esclarecedora.

Me temo que la respuesta a la pregunta "cómo definir tipos como este en TypeScript" es... No lo hacemos. La compatibilidad con JSX está integrada en el compilador. Sin embargo, hay muchas cosas interesantes que podemos personalizar.

over 4 years ago · Santiago Trujillo Report

0

La nota del manual de TS en la respuesta de Fabio explicó todo esto, solo quiero expandirme un poco. En resumen, TS no considera válidos los atributos de kebab-case, pero no generará un error; pero los atributos precedidos por data- o aria- se consideran válidos.

React ( desde 16 ) acepta atributos personalizados, es decir, <div foo /> y <div whateverYouLike={2}> deberían funcionar.

Lo que encuentro confuso con React es que data-* y aria-* deben escribirse tal cual, en lugar de convertirlos a camelCase como todo lo demás. Especialmente cuando estos atributos se convierten en camelCase en DOM vainilla:

 <div data-my-age="100" aria-label="A Test" />
 const $div = document.querySelector('#test') $div.dataset.myName = "D" console.log({ dataset: $div.dataset }) // { myAge: "100", myName: "D" } console.log($div.ariaLabel) // "A Test"

Nunca se dan razones para esto, por lo que solo podemos especular. Tal vez algo que ver con todas las herramientas, conveniencia de análisis, etc.

Las razones por las que <div foo /> arroja en TS es porque TS proporciona un conjunto estricto de nombres de propiedad válidos. Sin embargo, como se indica en la otra respuesta, TS no arrojará un error en random-foo porque se considera un identificador JS no válido. Mi especulación se debe a que los elementos DOM permiten propiedades arbitrarias, por lo que este es un compromiso que permite escribir correctamente en la mayoría de los casos en TS pero proporciona algún tipo de vía de escape. Me encantaría saber las razones detrás de estas decisiones.

¿Cómo definir tipos como este en TypeScript? es decir, solo permitir atributos estándar o de kebab-case.

Como ya ha señalado Fabio, el compilador incluye compatibilidad con JSX. Sin embargo, además de la capacidad de identificar lo que constituye un nombre de atributo válido, no creo que haya mucha magia: hay una lista completa de atributos DOM válidos. TS no arroja un error si mezcla casos de kebab y camello, es decir, <div data-myName> funciona, <div myName/> no, etc., por lo que tampoco difiere por el uso de mayúsculas y minúsculas.

Si conoce todos sus accesorios válidos de antemano, puede emular lo mismo.

 // allow only these prop names, which happened to be all camelCased interface MyThing { name: string myName: string anotherProp: string }

En el caso de kebab-case, los tipos de literales de plantilla podrían ser útiles:

 type ValidPrefix = "data" | "aria"; type ValidSuffix = "banana" | "apple" | "pear"; type ComputedProps = { [key in `${ValidPrefix}-${ValidSuffix}`]?: string; }; const x: ComputedProps = { "data-apple": 'hi' };

Más allá de esto, actualmente no hay ningún mecanismo en TS que pueda diferir entre camelCase y kebab-case string.


Si está buscando una forma de aumentar JSX para permitir accesorios personalizados y elementos personalizados, esta es una forma de hacerlo:

Aumento del atributo JSX para permitir accesorios personalizados y elementos personalizados

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!