admin管理员组文章数量:1404560
Given the following code:
import type {ReactNode} from 'react'
import React from 'react'
type Props = {
title: ReactNode
}
export const Comp: React.FC<Props> = ({title}) => {
return <div>{title}</div>
}
export const A = () => {
return <Comp title="smth" />
}
I want to find out what type has the title
property of Comp
component with the Typescript Compiler API
There is the only thing I've managed to do:
import {readFileSync} from 'node:fs'
import ts from 'typescript'
function checkJSXProperties(typescript: typeof ts, ctx: ts.TransformationContext, sf: ts.SourceFile) {
const visitor: ts.Visitor = node => {
if (ts.isJsxSelfClosingElement(node)) {
node.attributes.properties.forEach(attr => {
if (!ts.isJsxAttribute(attr)) {
return
}
const propertyName = attr.name.getText()
if (typeChecker.getTypeAtLocation(attr.name).flags & ts.TypeFlags.String) {
console.log(`Property '${propertyName}' inside props is of type 'string'`)
} else {
console.log(`Property '${propertyName}' inside props is NOT of type 'string'`)
}
})
}
return typescript.visitEachChild(node, visitor, ctx)
}
return visitor
}
const filePath = './src/scripts/index.tsx'
const program = ts.createProgram([filePath], {noEmit: true})
const typeChecker = program.getTypeChecker()
function transform(typescript: typeof ts): ts.TransformerFactory<ts.SourceFile> {
return ctx => sf => typescript.visitNode(sf, checkJSXProperties(typescript, ctx, sf))
}
const content = readFileSync(filePath).toString()
ts.transpileModule(content, {
compilerOptions: {
module: ts.ModuleKind.CommonJS,
jsxFactory: 'myJSXFactory',
jsx: ts.JsxEmit.React,
},
transformers: {
before: [transform(ts)],
},
})
which outputs the following:
Property 'title' inside props is of type 'string'
But that's incorrect according to the Props
type which tells that title
prop if of type ReactNode
How can I get the type of jsx property, not the type of js property value with TS Compiler API? Or is there any other tool that can help me?
Given the following code:
import type {ReactNode} from 'react'
import React from 'react'
type Props = {
title: ReactNode
}
export const Comp: React.FC<Props> = ({title}) => {
return <div>{title}</div>
}
export const A = () => {
return <Comp title="smth" />
}
I want to find out what type has the title
property of Comp
component with the Typescript Compiler API
There is the only thing I've managed to do:
import {readFileSync} from 'node:fs'
import ts from 'typescript'
function checkJSXProperties(typescript: typeof ts, ctx: ts.TransformationContext, sf: ts.SourceFile) {
const visitor: ts.Visitor = node => {
if (ts.isJsxSelfClosingElement(node)) {
node.attributes.properties.forEach(attr => {
if (!ts.isJsxAttribute(attr)) {
return
}
const propertyName = attr.name.getText()
if (typeChecker.getTypeAtLocation(attr.name).flags & ts.TypeFlags.String) {
console.log(`Property '${propertyName}' inside props is of type 'string'`)
} else {
console.log(`Property '${propertyName}' inside props is NOT of type 'string'`)
}
})
}
return typescript.visitEachChild(node, visitor, ctx)
}
return visitor
}
const filePath = './src/scripts/index.tsx'
const program = ts.createProgram([filePath], {noEmit: true})
const typeChecker = program.getTypeChecker()
function transform(typescript: typeof ts): ts.TransformerFactory<ts.SourceFile> {
return ctx => sf => typescript.visitNode(sf, checkJSXProperties(typescript, ctx, sf))
}
const content = readFileSync(filePath).toString()
ts.transpileModule(content, {
compilerOptions: {
module: ts.ModuleKind.CommonJS,
jsxFactory: 'myJSXFactory',
jsx: ts.JsxEmit.React,
},
transformers: {
before: [transform(ts)],
},
})
which outputs the following:
Property 'title' inside props is of type 'string'
But that's incorrect according to the Props
type which tells that title
prop if of type ReactNode
How can I get the type of jsx property, not the type of js property value with TS Compiler API? Or is there any other tool that can help me?
Share Improve this question edited Mar 10 at 17:25 Volok asked Mar 10 at 15:04 VolokVolok 736 bronze badges1 Answer
Reset to default 0In this use case, ReactNode is not the right option for determining if the property is a JSX element. With its flexibility, ReactNode can be applied to one of theese types:
- Boolean
- null or undefined
- Number = String
- A React element (result of JSX)
- An array of any of the above
but it can't be ReactNode
. when you want to get the type of the title property it would not be ReactNode, it will be one of the above types according to ReactNode type definition:
type ReactNode = string | number | bigint | boolean | React.ReactElement<any, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | React.ReactPortal | Promise<...> | null | undefined
use React.isValidElement() function
You can use isValidElement() which returns a boolean to determine if it is a JSX element or a React element or not.export const Comp: React.FC<Props> = ({ title }) => {
const isElement = React.isValidElement(title)
console.log(isElement)
return <div>{title}</div>
}
const Test = () => {
return (
<div>
<p>test</p>
</div>
)
}
export const A = () => {
return <Comp title={<Test />} /> // print: true
}
export const B = () => {
return <Comp title={<p>hi</p>} /> // print: true
}
export const C = () => {
return <Comp title={123} /> // print: false
}
if you want typescript to only consider jsx element you can use:
type Props = {
title: React.ReactElement<keyof JSX.IntrinsicElements> // React components are not allowed.
}
本文标签: reactjsTS Compiler API Get jsx component property typeStack Overflow
版权声明:本文标题:reactjs - TS Compiler API: Get jsx component property type - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744839319a2627823.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论