我已经创建了一个自定义的Checkbox
组件。
项目中的TypeScript不接受any
类型,因此我需要指示handleCheckbox()
函数(位于FilterBox
组件中(的确切类型,该函数将作为道具传递给子组件Checkbox
。
const handleCheckbox = (state: Record<string, unknown>) => {
const _preProcessNewState = { ...globalStatus, ...state };
//Change the States
setGlobalStatus(_preProcessNewState);
};
下面我们将此函数传递给复选框:
<Checkbox
text={t(TranslationConstants.Map.asapOrderInFilter)}
property={t(TranslationConstants.Map.checkboxAsapProperty)}
checked={globalStatus['asap']}
fn={handleCheckbox.bind(this)}
/>
现在,在复选框组件中,我需要声明fn((的正确类型:
import { useState, useEffect } from 'react';
type checkboxProps = {
text: string;
checked: boolean;
fn: (e: any) => void;
property: string;
};
const CheckBox = (props: checkboxProps) => {
const { text, checked, fn, property } = props;
const [statusCheck, setStatusCheck] = useState(checked);
const handleChange = () => {
const _newState = !statusCheck;
setStatusCheck(_newState);
fn({ [property]: _newState });
};
useEffect(() => {
setStatusCheck(checked);
}, [checked]);
return (
<div>
{' '}
<label>
{' '}
<input
type="checkbox"
checked={statusCheck}
onChange={handleChange}
/>{' '}
{text}
</label>{' '}
</div>
);
};
export default CheckBox;
我试过HTMLInputElement,React.HTMLInputElement,但没用。
如果您需要更多上下文,下面是完整的代码:https://codesandbox.io/s/quizzical-gould-d4bry?file=/src/App.tsx
除此之外,我还需要修复OrderList中的任何类型。如果存在任何类型,则所有构建都会中断,因此声明正确的类型至关重要。
我需要指示handleCheckbox((函数的确切类型(位于FilterBox组件中(,我将其作为道具传递给子组件Checkbox
我想你的意思是,你需要改进checkboxProps["fn"]
的定义(这是你将handleCheckbox
传递给的道具(,以避免使用any
:
type checkboxProps = {
text: string;
checked: boolean;
fn: (e: any) => void;
// It throws warning here. Here is where I need to indicate type for e: and returning value (not sure if it's void)
property: string;
};
我尝试过HTMLInputElement,React.HTMLInputElement
如果fn
道具函数作为<input>
的事件监听器被直接调用,本可以处于正确的轨道上。
但是您有一个介于两者之间的handleChange
函数,它以不同于简单事件侦听器的方式调用fn
:
<input
type="checkbox"
checked={statusCheck}
onChange={handleChange}
/>
const handleChange = () => {
const _newState = !statusCheck;
setStatusCheck(_newState);
fn({ [property]: _newState });
};
handleChange
函数不使用您的事件参数,因此实际上不需要查找此类事件类型。
它使用1个参数{ [property]: _newState }
调用fn
道具函数,该参数的类型为Record<string, boolean>
。
因此,您可以将fn
道具定义为:fn: (newState: Record<string, boolean>) => void;
还可以进一步定义类型,以指示它有一个由property
道具字符串定义的成员,但这将在几个地方涉及泛型。
另一方面,在我看来,您的checkboxProps
类型比它可能的更复杂:您正在传递一个属性名称,该名称仅用于构建一个要传递给fn
道具回调的特定对象。在这种情况下,更简单的做法是直接向它传递空的新检查值,并让回调处理其对象和属性名称,这是父组件已知的(在您的情况下是FilterBox
(。这样,就可以避免传递property
字符串,并打破FilterBox
和Checkbox
之间的强耦合:现在您的Checkbox
组件可以与其他父组件一起使用,这些组件可能不使用任何对象状态。
type checkboxProps = {
text: string;
checked: boolean;
fn: (newIsChecked: boolean) => void;
};
// In Checkbox component
const handleChange = () => {
const _newState = !statusCheck;
setStatusCheck(_newState);
fn(_newState);
};
// In FilterBox component (or any other parent component)
<Checkbox
text={t(TranslationConstants.Map.asapOrderInFilter)}
checked={globalStatus['asap']}
fn={(newIsChecked) => {
handleCheckbox({
asap: newIsChecked
});
}}
/>
然后,如果您想避免在多次使用具有不同属性名称的<Checkbox>
组件时手动构建回调,您可以创建一个生成函数,例如在以下行中:
function makeHandleCheckboxFnForProperty(propertyName: string) {
return (newIsChecked: boolean) => {
handleCheckbox({
[propertyName]: newIsChecked
});
}
}
然后在您的模板中:
<Checkbox
text={t(TranslationConstants.Map.asapOrderInFilter)}
checked={globalStatus['asap']}
fn={makeHandleCheckboxFnForProperty('asap')}
/>