我想在 TypeScript 中使用 JSX 语法,但不想使用 React。
我在这里看到了其他相关问题的答案,但没有任何内容足够完整或详细,无法提供任何帮助。我已经阅读了本指南和手册中的JSX 章节,但没有多大帮助。我不明白语言功能本身是如何工作的。
我尝试检查 React 声明,但它对我来说太大了,无法吸收 - 我需要一个最小的、有效的示例来演示类型检查的元素、组件和属性。(它不需要工厂函数的有效实现,我最感兴趣的是声明。)
我至少想要一个能够实现以下工作且具有类型安全性的示例:
var el = <Ping blurt="ya"></Ping>;
var div = <div id="foo">Hello JSX! {el}</div>;
Run Code Online (Sandbox Code Playgroud)
JSX.IntrinsicElements我想我至少需要声明createElement()某种工厂函数,但这就是我所得到的:
declare module JSX {
interface IntrinsicElements {
div: flurp.VNode<HTMLDivElement>;
}
}
module flurp {
export interface VNode<E extends Element> {
id: string
}
export function createElement<T extends Element>(type: string, props?: any, ...children: (VNode<Element>|string)[]): VNode<Element> {
return {
id: props["id"]
};
}
}
class Ping {
// ???
}
var el = <Ping blurt="ya"></Ping>;
var div = <div id="foo">Hello JSX! {el}</div>;
Run Code Online (Sandbox Code Playgroud)
我用这样的方式编译它tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"jsx": "react",
"reactNamespace": "flurp"
}
}
Run Code Online (Sandbox Code Playgroud)
将鼠标悬停在<div>元素和id="foo"属性上,我可以看到编译器理解我的内在元素声明 - 到目前为止,一切顺利。
现在,要<Ping blurt="ya">通过属性的类型检查来编译声明blurt,我该怎么办?甚至应该Ping是 aclass还是可能是 afunction或者什么?
理想情况下,元素和组件应该具有某种共同的祖先,因此我可以拥有一组适用于两者的共同属性。
我希望创建一些简单且轻量级的东西,可能类似于 Monkberry ,但使用 JSX 语法,例如使用像<If>and 之类的组件<For>而不是内联语句。这可行吗?(有没有类似的现有项目可供我参考?)
请,如果有人可以提供一个如何使用语言功能本身的有效的、最小的示例,那将是一个巨大的帮助!
Con*_*Low 15
事实上,TypeScript 手册的 JSX 部分是一个很好的资源;对于那些还没有看过的人,请检查一下。
如果您想tsc编译 JSX,您将需要执行以下操作(极其广泛的概述):
IntrinsicElements/类型JSX(启用类型安全)。"react"(或另一个 jsx 选项)代码生成并指向您的 JSX Factory(使用该"jsxFactory"选项)。这是对此进行更深入的了解。另外,您可能想查看存储库或工作示例/游乐场。
在这里,您告诉 TypeScript 如何解释您的 JSX 代码。至少,您需要声明IntrinsicElements,但您还可以声明其他类型,这些类型将为您提供更好的类型提示、启用组件功能,并通常改进/调整 TypeScript 对 JSX 的理解方式。
以下是 JSX 命名空间的声明示例:
/// <reference lib="DOM" />
declare namespace JSX {
// The return type of our JSX Factory: this could be anything
type Element = HTMLElement;
// IntrinsicElementMap grabs all the standard HTML tags in the TS DOM lib.
interface IntrinsicElements extends IntrinsicElementMap { }
// The following are custom types, not part of TS's known JSX namespace:
type IntrinsicElementMap = {
[K in keyof HTMLElementTagNameMap]: {
[k: string]: any
}
}
interface Component {
(properties?: { [key: string]: any }, children?: Node[]): Node
}
}
Run Code Online (Sandbox Code Playgroud)
一些注意事项:
HTMLElements 和Nodes,DOM 库 ( lib.dom.d.ts ) 是一个很好的资源,可以帮助您更好地进行类型检查。在此示例中,我使用它来将所有真实的 HTML 标记声明为有效的内部元素。您可以进一步扩展它,例如,预加载viaEventHandler之类的。onclickGlobalEventHandlersElement是 TypeScript 在 JSX 命名空间中查找的另一种类型。这是可选的(默认为any)。使用它来指定工厂函数的返回类型。Component接口定义了一个自定义帮助器)。JSX.ElementClass接口。请参阅此处了解更多详细信息。命名JSX空间帮助我们定义如何在代码中使用 JSX,但我们仍然需要实现一个可以处理tsc. 我们的工厂函数应该遵循表格(tag: string, properties: { [k: string]: any }, ...children: any[]): any,或者更具体的东西。这是一个启用功能组件的示例(注意它又大又丑):
function jsx(tag: JSX.Tag | JSX.Component,
attributes: { [key: string]: any } | null,
...children: Node[])
{
if (typeof tag === 'function') {
return tag(attributes ?? {}, children);
}
type Tag = typeof tag;
const element: HTMLElementTagNameMap[Tag] = document.createElement(tag);
// Assign attributes:
let map = (attributes ?? {});
let prop: keyof typeof map;
for (prop of (Object.keys(map) as any)) {
// Extract values:
prop = prop.toString();
const value = map[prop] as any;
const anyReference = element as any;
if (typeof anyReference[prop] === 'undefined') {
// As a fallback, attempt to set an attribute:
element.setAttribute(prop, value);
} else {
anyReference[prop] = value;
}
}
// append children
for (let child of children) {
if (typeof child === 'string') {
element.innerText += child;
continue;
}
if (Array.isArray(child)) {
element.append(...child);
continue;
}
element.appendChild(child);
}
return element;
}
Run Code Online (Sandbox Code Playgroud)
现在,剩下的就是使用我们的jsx函数了。我们的 tsconfig 至少应该配置以下内容:
{
"compilerOptions": {
"jsx": "react", // or react-jsx, etc.
"jsxFactory": "jsx",
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以在任何文件中编写 JSX .tsx,只要我们导入jsxFactory:
import jsx from './jsxFactory';
function Ping({ blurt }: { blurt: string }) {
return <div>{blurt}</div>
}
var el = <Ping blurt="ya"></Ping>;
// var div: HTMLElement
var div = <div id="foo">Hello JSX! {el}</div>;
document.body.appendChild(div)
Run Code Online (Sandbox Code Playgroud)
感谢JSX.ElementTypeScript 知道 JSX 的结果是一个HTMLElement.
| 归档时间: |
|
| 查看次数: |
5043 次 |
| 最近记录: |