Typescript is pretty good about inferred generic types. For example, if I write the following code:
class AwesomeClass<T> {
constructor(public val: T) {
// ...
}
public getVal(): T {
return this.val;
}
}
const inst = new AwesomeClass("Hello World");
const result = inst.getVal();
result
is automatically typed to string
. Nifty! I'd like to take that a step further with React.
If I make the follow component
interface IProps<T> {
value: T;
onClick: (result: T) => void;
}
interface IState { }
class AwesomeComponent<T> extends React.Component<IProps<T>, IState> {
// ...
}
I'd really like it to be inferred that value
has to have the same type as the result
argument of onClick
. Instead when I initialize the component with
<AwesomeComponent
value="Hello World"
onClick={(v) => { console.log(v); }} />;
I get a compile error error TS2322: Type 'string' is not assignable to type 'T'
.
Is it possible to infer the generic type on a React element's props?
I realize that the JSX transpiles to a call to React.createElement
(it doesn't directly initialize the class like I do with my AwesomeClass
example above) and that this may complicate the process - is that a deal killer? If so, can I explicitly name a generic type using the JSX syntax?
This isn't possible yet, here's an issue about it: Using lookahead to detect generic JSX elements? .
For now what you'll need to do is:
interface IProps<T> {
value: T;
onClick: (result: T) => void;
}
interface IState { }
class AwesomeComponent<T> extends React.Component<IProps<T>, IState> {
// ...
}
class ConcreteAwesomeComponent extends AwesomeComponent<string> {}
<ConcreteAwesomeComponent
value="Hello World"
onClick={(v) => { console.log(v); }} />;
for using functional component you can use this code
interface IMessagesProps<T> {
data: T[];
titleName: keyof T;
type: MESSAGE_SYSTEM_TYPE;
}
const Messages = <T extends Record<keyof T, unknown>>(props: IMessagesProps<T>) => {
const { data, type, titleName } = props;
return (
<>
{data?.length ? (
data.map((message, index) => {
return (
<div key={index}>
<p >{message[titleName]}</p>
</div>
);
})
) : (
<div>Empty</div>
)}
</>
);
};
export default Messages;
then you use Messages component like this :
interface IMarketNoticeResponse {
id: string;
message: string;
}
const messagesDisplayList : IMarketNoticeResponse[] = [
{id:"1",message:"message1"},
{id:"2",message:"message2"}]
<Messages<IMarketNoticeResponse>
data={messagesDisplayList}
titleName="message"
type={messageType}
/>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.