如何自定义 jsx(tsx) 语法的结果?
例如 我有一个 User 的 class,我希望变量 a 的效果 和变量 b 是一样的,并且 在 .tsx 文件中要能正确的推导类型
class User {}
let a = <User />
let b = new User()
在 vite 中这样是可以的,js 的运行结果是符合期望的,但是类型推导不出来
如何自定义 jsx(tsx) 语法的结果?
例如 我有一个 User 的 class,我希望变量 a 的效果 和变量 b 是一样的,并且 在 .tsx 文件中要能正确的推导类型
class User {}
let a = <User />
let b = new User()
在 vite 中这样是可以的,js 的运行结果是符合期望的,但是类型推导不出来
要在 TypeScript 中自定义 JSX(或 TSX)语法的结果,并使其类型推导正确,你需要使用 TypeScript 的 JSX 工厂机制。默认情况下,JSX 语法被编译为 React.createElement
调用,但你可以通过配置 jsx
编译选项来自定义这个行为。
对于你的需求,由于你希望 <User />
语法能够生成一个 User
类的实例而不是一个 React 元素,你需要自定义 JSX 的转换行为。然而,直接通过 TypeScript 配置实现这一点并不直接支持,因为 JSX 本质上是为 React 设计的。不过,你可以通过一些变通方法来实现类似的效果。
虽然这种方法不直接适用于你的需求(因为 JSX 本质上是为 React 设计的,而不是用于实例化类),但这里展示如何自定义 JSX 工厂:
定义一个工厂函数:
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;
}
配置 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 语法来实例化类并不现实。相反,使用工厂函数或辅助函数是更合适的方法,它们可以保持类型安全并清晰地表达你的意图。
2 回答1.5k 阅读✓ 已解决
2 回答1.7k 阅读✓ 已解决
2 回答2k 阅读✓ 已解决
3 回答2.4k 阅读
3 回答1.4k 阅读✓ 已解决
2 回答943 阅读✓ 已解决
1 回答1.2k 阅读✓ 已解决
目前最新版本的TS是做不到的。
但可以自己修改源码或等待官方支持。