我正在查看this question ,我认为这与我的问题有关。但是,它与我的用例有点不同。
我有一个名为 parseScanResults
的函数,它接受一个对象参数。该对象可以是两种类型之一。但是, typescript 使用以下代码抛出错误:
const ScanForm: React.FC<IScanFormProps> = ({ children, onSubmit, parseScanResults }) => {
const [scannerActive, toggleScannerActive] = useState(false);
const closeScanner = (): void => {
toggleScannerActive(false);
};
const handleScanResults = (results: IVoucherScanResults | IBlinkCardScanResults): void => {
const { cardString, stringMonth, stringYear } = parseScanResults(results);
setValue('cardNumber', cardString);
setValue('expMonth', stringMonth);
setValue('expYear', stringYear);
toggleScannerActive(false);
};
return (
<Form onSubmit={handleSubmit(onSubmit)}>
{children({ scannerActive, closeScanner, handleScanResults })}
</Form>
);
};
import CreditCardBarcodeScanner from 'src/components/scanners/credit_card_barcode_scanner';
import { IVoucherScanResults, IScannerProps, IParsedScanResults } from '../scanners/card_scanners';
import ScanForm from './scan-form';
function CreditCardBarcodeForm(): JSX.Element {
const onSubmit = (data: { expMonth: string; expYear: string; securityCode: string; cardNumber: string }): void => {
// Do something with form data
console.log(data);
};
const parseScanResults = (results: IVoucherScanResults): IParsedScanResults => {
const { text } = results;
const [cardString, expirationString] = text.slice().split('/');
const stringMonth = expirationString.slice(0, 2);
const stringYear = expirationString.slice(2, 4);
return { cardString, stringMonth, stringYear };
};
return (
<ScanForm onSubmit={onSubmit} parseScanResults={parseScanResults}>
{({ scannerActive, closeScanner, handleScanResults }: IScannerProps) => (
<CreditCardBarcodeScanner
scannerActive={scannerActive}
closeScanner={closeScanner}
handleScanResults={handleScanResults}
/>
)}
</ScanForm>
);
}
export default CreditCardBarcodeForm;
export interface IBlinkCardScanResults {
cardNumber: string;
cvv: string;
expiryDate: {
day?: number;
empty?: boolean;
month: number;
originalString?: string;
successfullyParsed?: boolean;
year: number;
};
}
export interface IVoucherScanResults {
text: string;
timestamp: number;
format: number;
numBits: number;
}
export interface IParsedScanResults {
cardString: string;
stringMonth: string;
stringYear: string;
}
export interface IScannerProps {
scannerActive: boolean;
closeScanner: () => void;
handleScanResults: (results: IVoucherScanResults | IBlinkCardScanResults) => void;
}
export interface IScanFormProps {
children: (props: ICardScannerProps) => React.ReactElement;
onSubmit: (data: { expMonth: string; expYear: string; securityCode: string; cardNumber: string }) => void;
parseScanResults: (results: IBlinkCardScanResults | IVoucherScanResults) => IParsedScanResults;
}
错误状态:
Type '(results: IVoucherScanResults) => IParsedScanResults' is not assignable to type '(results: IBlinkCardScanResults | IVoucherScanResults) => IParsedScanResults'.
Types of parameters 'results' and 'results' are incompatible.
Type 'IBlinkCardScanResults | IVoucherScanResults' is not assignable to type 'IVoucherScanResults'.
Type 'IBlinkCardScanResults' is missing the following properties from type 'IVoucherScanResults': text, timestamp, format, numBitsts(2322)
最佳答案
你的问题是parseScanUtils
是一个函数,它得到 IVoucherScanResults
作为参数,或函数,获取 IBlinkCardScanResults
作为参数,而只有一个为真。在这种情况下,您的组件似乎正在接收两个中的第一个。
主要的一点是,拥有一个函数的联合(其中每个函数都获取特定的参数类型)和拥有一个其参数是两种类型的联合的函数之间存在差异。
parseScanResults:
((results: IBlinkCardScanResults) => IParsedScanResults)
| ((results: IVoucherScanResults) => IParsedScanResults);
对比
parseScanResults:
((results: IBlinkCardScanResults | IVoucherScanResults) => IParsedScanResults)
编辑
您可以做的是使用泛型,而不是键入组件函数,您可以显式键入参数:
让我们首先使界面通用:
export interface IScanFormProps<T extends IBlinkCardScanResults | IVoucherScanResults> {
children: (props: ICardScannerProps) => React.ReactElement;
onSubmit: (data: { expMonth: string; expYear: string; securityCode: string; cardNumber: string }) => void;
parseScanResults: (results: T) => IParsedScanResults;
}
您可以像这样更新您的功能组件:
const ScanForm = <T extends IBlinkCardScanResults | IVoucherScanResults>({ children, onSubmit, parseScanResults }: T) => {
还有你的handleScanResults
功能:
const handleScanResults = (results: T): void => {
...rest of code...
}
然后剩下要做的就是调用具有所需类型的组件(例如 IBlinkCardScanResults
):
<ScanForm<IBlinkCardScanResults> onSubmit={onSubmit} parseScanResults={parseScanResults}>
我相信现在应该可以了
关于javascript - Typescript:函数参数是两个接口(interface)之一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68024197/