如何自定义 jsx(tsx) 语法的结果?

如何自定义 jsx(tsx) 语法的结果?

例如 我有一个 User 的 class,我希望变量 a 的效果 和变量 b 是一样的,并且 在 .tsx 文件中要能正确的推导类型

class User {}

let a = <User />

let b = new User()

在 vite 中这样是可以的,js 的运行结果是符合期望的,但是类型推导不出来
image.png

阅读 606
avatarAI BotBETA

要在 TypeScript 中自定义 JSX(或 TSX)语法的结果,并使其类型推导正确,你需要使用 TypeScript 的 JSX 工厂机制。默认情况下,JSX 语法被编译为 React.createElement 调用,但你可以通过配置 jsx 编译选项来自定义这个行为。

对于你的需求,由于你希望 <User /> 语法能够生成一个 User 类的实例而不是一个 React 元素,你需要自定义 JSX 的转换行为。然而,直接通过 TypeScript 配置实现这一点并不直接支持,因为 JSX 本质上是为 React 设计的。不过,你可以通过一些变通方法来实现类似的效果。

方法一:使用自定义 JSX 工厂(不推荐用于此场景,但展示原理)

虽然这种方法不直接适用于你的需求(因为 JSX 本质上是为 React 设计的,而不是用于实例化类),但这里展示如何自定义 JSX 工厂:

  1. 定义一个工厂函数

    interface JSX {
        IntrinsicElements: {
            [elemName: string]: any;
        }
    }
    
    declare global {
        namespace JSX {
            interface Element {}
            interface IntrinsicElements {
                user: User;
            }
        }
    }
    
    function jsxFactory(type: any, props?: any, ...children: any[]): any {
        if (type === 'user') {
            return new User();
        }
        // 其他类型的处理
        return null;
    }
  2. 配置 tsconfig.json

    {
        "compilerOptions": {
            "jsx": "react-jsx", // 或者 "react-jsxdev" 根据你的需求
            "jsxFactory": "jsxFactory",
            "jsxImportSource": "./path/to/jsxFactoryFile" // 指向包含 jsxFactory 的文件
        }
    }
**注意**:这种方法不适用于直接使用 `<User />` 这样的泛型标签,因为 JSX 标签名通常是小写开头的,而类名是大写开头的。此外,这种方法更适用于自定义元素而不是类实例。

方法二:使用工厂函数或辅助函数

对于你的具体需求,更合适的方法是使用工厂函数或辅助函数来创建 User 实例,而不是试图通过修改 JSX 语法来实现。

class User {}

// 定义一个工厂函数
function createUser(): User {
    return new User();
}

// 使用工厂函数
let a = createUser();
let b = new User();

.tsx 文件中,你可以继续使用这个工厂函数来保持类型安全,而无需修改 JSX 的默认行为。

结论

由于 JSX 语法是为 React 设计的,并且 TypeScript 的 JSX 支持也是围绕这个目的构建的,因此直接通过修改 JSX 语法来实例化类并不现实。相反,使用工厂函数或辅助函数是更合适的方法,它们可以保持类型安全并清晰地表达你的意图。

1 个回答

目前最新版本的TS是做不到的。
但可以自己修改源码或等待官方支持。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏