React 组件的推断通用类型
Inferred Generic Type on React Component
Typescript 非常适合推断泛型类型。例如,如果我编写以下代码:
class AwesomeClass<T> {
constructor(public val: T) {
// ...
}
public getVal(): T {
return this.val;
}
}
const inst = new AwesomeClass("Hello World");
const result = inst.getVal();
result
自动输入为 string
。漂亮!我想用 React 更进一步。
如果我制作跟随组件
interface IProps<T> {
value: T;
onClick: (result: T) => void;
}
interface IState { }
class AwesomeComponent<T> extends React.Component<IProps<T>, IState> {
// ...
}
我真的很想推断 value
必须与 onClick
的 result
参数具有相同的类型。相反,当我用
初始化组件时
<AwesomeComponent
value="Hello World"
onClick={(v) => { console.log(v); }} />;
我收到编译错误 error TS2322: Type 'string' is not assignable to type 'T'
。
是否可以推断 React 元素的 props 的泛型类型?
我意识到 JSX 转换为对 React.createElement
的调用(它不会像我在上面的 AwesomeClass
示例中那样直接初始化 class)并且这可能使流程复杂化——这是一个交易杀手吗?如果是这样,我可以使用 JSX 语法显式命名泛型类型吗?
这还不可能,这里有一个问题:Using lookahead to detect generic JSX elements?。
现在您需要做的是:
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); }} />;
要使用功能组件,您可以使用此代码
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;
然后你像这样使用 Messages 组件 :
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}
/>
Typescript 非常适合推断泛型类型。例如,如果我编写以下代码:
class AwesomeClass<T> {
constructor(public val: T) {
// ...
}
public getVal(): T {
return this.val;
}
}
const inst = new AwesomeClass("Hello World");
const result = inst.getVal();
result
自动输入为 string
。漂亮!我想用 React 更进一步。
如果我制作跟随组件
interface IProps<T> {
value: T;
onClick: (result: T) => void;
}
interface IState { }
class AwesomeComponent<T> extends React.Component<IProps<T>, IState> {
// ...
}
我真的很想推断 value
必须与 onClick
的 result
参数具有相同的类型。相反,当我用
<AwesomeComponent
value="Hello World"
onClick={(v) => { console.log(v); }} />;
我收到编译错误 error TS2322: Type 'string' is not assignable to type 'T'
。
是否可以推断 React 元素的 props 的泛型类型?
我意识到 JSX 转换为对 React.createElement
的调用(它不会像我在上面的 AwesomeClass
示例中那样直接初始化 class)并且这可能使流程复杂化——这是一个交易杀手吗?如果是这样,我可以使用 JSX 语法显式命名泛型类型吗?
这还不可能,这里有一个问题:Using lookahead to detect generic JSX elements?。
现在您需要做的是:
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); }} />;
要使用功能组件,您可以使用此代码
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;
然后你像这样使用 Messages 组件 :
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}
/>