Wen*_* Du 14 javascript jsx typescript reactjs vue.js
使用foo作为属性抛出一个错误:
// App.tsx
// throws
const App = () => <div foo></div>
export default App
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
但使用foo-foo是好的,为什么呢?
// App.tsx
// no error is thrown
const App = () => <div foo-foo></div>
export default App
Run Code Online (Sandbox Code Playgroud)
最重要的是,如何在 TypeScript 中定义这样的类型?即只允许标准或 kebab-case 属性。
Fáb*_*sta 11
答案在Typescript 手册的JSX 部分:
如果属性名称不是有效的JS 标识符(如
data-*属性),如果在元素属性类型中找不到,则不认为是错误。
JSX 的整个部分是一本非常有启发性的读物。
恐怕“如何在 TypeScript 中定义这样的类型”问题的答案是......我们没有。JSX 支持内置于编译器中。然而,我们可以自定义很多有趣的东西。
Der*_*yen 10
Fabio 的回答中的 TS 手册说明解释了所有这些,只是想扩展一点。简而言之,kebab-case 属性不被 TS 认为是有效的,但不会抛出错误;但以data-oraria-为前缀的属性被认为是有效的。
React(从 16 开始)接受自定义属性,即<div foo />并且<div whateverYouLike={2}>应该可以工作。
我找到与之反应混淆什么,是data-*和aria-*应该写成-是,与它们转换为驼峰其他事物一样。特别是当这些属性在 vanilla DOM 中转换为驼峰式大小写时:
<div data-my-age="100" aria-label="A Test" />
Run Code Online (Sandbox Code Playgroud)
<div data-my-age="100" aria-label="A Test" />
Run Code Online (Sandbox Code Playgroud)
没有给出任何理由,所以我们只能推测。也许与 a11y 工具、解析方便等有关。
<div foo />抛出 TS的原因是因为 TS 提供了一组严格的有效属性名称。但是,正如另一个答案所指出的,TS 不会抛出错误,random-foo因为它被认为是无效的 JS 标识符。我的推测是因为 DOM 元素允许任意属性,所以这是一种妥协,允许在大多数情况下在 TS 中正确键入但提供某种逃生舱口。很想知道这些决定背后的原因。
如何在 TypeScript 中定义这样的类型?即只允许标准或 kebab-case 属性。
正如 Fabio 已经指出的那样,编译器内置了 JSX 支持。然而,除了能够识别构成有效属性名称的内容之外,我认为它没有什么神奇之处:有一个完整的有效 DOM 属性列表。如果您混合使用 kebab 和骆驼案例,TS 不会抛出错误,即<div data-myName>工作,<div myName/>不工作等,因此它也不会因大小写而有所不同。
如果您事先知道所有有效道具,则可以模拟相同的事情。
// allow only these prop names, which happened to be all camelCased
interface MyThing {
name: string
myName: string
anotherProp: string
}
Run Code Online (Sandbox Code Playgroud)
在 kebab-case 的情况下,模板文字类型可能会有所帮助:
type ValidPrefix = "data" | "aria";
type ValidSuffix = "banana" | "apple" | "pear";
type ComputedProps = {
[key in `${ValidPrefix}-${ValidSuffix}`]?: string;
};
const x: ComputedProps = {
"data-apple": 'hi'
};
Run Code Online (Sandbox Code Playgroud)
除此之外,目前 TS 中没有任何机制可以在驼峰式字符串和烤肉串字符串之间有所不同。
如果您正在寻找一种方法来增强 JSX 以允许自定义道具和自定义元素,这是一种方法:
| 归档时间: |
|
| 查看次数: |
348 次 |
| 最近记录: |