reactjs - MUIv4 nadogradnja s TypeScriptom - Ne mogu pravilno proširiti props na TextField
Trenutna verzija Material-UI: 4.1.0
Imam problema s prosljeđivanjem props-a apstraktnoj <TextField /> komponenti koju sam stvorio.
Evo koda:
PasswordInput.tsximport * as React from 'react'
import TextField, { Props as TextFieldProps } from 'src/TextField'
type Props = TextFieldProps & {
hideHelperText?: boolean;
};
class PasswordInput extends React.Component<Props> {
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
/** do stuff */
};
render() {
const {
hideHelperText,
classes,
...rest
} = this.props;
return (
<React.Fragment>
<TextField
/** errors out here */
/*
Type 'HideShowText | null' is not assignable to type 'HTMLDivElement | null'.
Type 'HideShowText' is missing the following properties from type 'HTMLDivElement':
align, addEventListener, removeEventListener, accessKey, and 238 more
*/
{...rest}
onChange={this.onChange}
/>
{!hideHelperText && 'hello world'}
</React.Fragment>
);
}
}
export default PasswordInput;
TextField.tsximport TextField, {
StandardTextFieldProps as TextFieldProps
} from '@material-ui/core/TextField';
type ClassNames =
| 'root'
const styles = (theme: Theme) =>
createStyles({
root: {},
});
interface BaseProps {
tooltipText?: string;
dataAttrs?: Record<string, any>
}
export type Props = BaseProps & TextFieldProps
type CombinedProps = Props &
WithStyles<ClassNames>;
class MyTextField extends React.Component<CombinedProps> {
render() {
const {
children,
tooltipText,
dataAttrs,
/** everything else that goes on the root */
...textFieldProps
} = this.props;
return (
<div
>
<TextField
{...textFieldProps}
{...dataAttrs}
>
{this.props.children}
</TextField>
{tooltipText && <HelpIcon text={tooltipText} />}
</div>
);
}
}
const styled = withStyles(styles);
export default compose<CombinedProps, Props>(
styled
)(MyTextField);
Puca s sljedećom pogreškom:
TS2322: Type '{ tooltipText: string | undefined; value: string | undefined; onChange: (e: ChangeEvent<HTMLInputElement>) => void; fullWidth: true; required: boolean | undefined; errorText?: string | undefined; ... 282 more ...; innerRef?: ((instance: any) => void) | ... 2 more ... | undefined; }' is not assignable to type 'IntrinsicClassAttributes<HideShowText>'.
Types of property 'ref' are incompatible.
Type '((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null | undefined' is not assignable to type 'string | ((instance: HideShowText | null) => void) | RefObject<HideShowText> | null | undefined'.
Type '(instance: HTMLDivElement | null) => void' is not assignable to type 'string | ((instance: HideShowText | null) => void) | RefObject<HideShowText> | null | undefined'.
Type '(instance: HTMLDivElement | null) => void' is not assignable to type '(instance: HideShowText | null) => void'.
Types of parameters 'instance' and 'instance' are incompatible.
Type 'PasswordInput | null' is not assignable to type 'HTMLDivElement | null'.
Type 'PasswordInput' is missing the following properties from type 'HTMLDivElement': align, addEventListener, removeEventListener, accessKey, and 238 more.
Čini se da ...rest u PasswordInputu treba biti jednako StandardTextFieldProps, ali iz nekog razloga dobivam pogreške da moja komponenta nije HTMLDivElement?
Javi mi ako mogu dati više detalja. Koliko ja mogu zaključiti, ovo je greška.
Odgovor #1
@flatline. Hvala na prijedlogu. Također sam imao funkcionalno rješenje u promjeni načina na koji je izvoženje napisano. Iskreno, nisam siguran zašto ovo radi, ali radi. Obratite pažnju na posljednje redove u svakoj datoteci:
TextField.tsx
import TextField, {
StandardTextFieldProps as TextFieldProps
} from '@material-ui/core/TextField';
type ClassNames =
| 'root'
const styles = (theme: Theme) =>
createStyles({
root: {},
});
interface BaseProps {
tooltipText?: string;
dataAttrs?: Record<string, any>
}
export type Props = BaseProps & TextFieldProps
type CombinedProps = Props &
WithStyles<ClassNames>;
class MyTextField extends React.Component<CombinedProps> {
render() {
const {
children,
tooltipText,
dataAttrs,
/** everything else that goes on the root */
...textFieldProps
} = this.props;
return (
<div
>
<TextField
{...textFieldProps}
{...dataAttrs}
>
{this.props.children}
</TextField>
{tooltipText && <HelpIcon text={tooltipText} />}
</div>
);
}
}
const styled = withStyles(styles);
export default compose<CombinedProps, Props>(
styled
)(MyTextField) as s React.ComponentType<Props>;;
PasswordInput.tsx
import * as React from 'react'
import TextField, { Props as TextFieldProps } from 'src/TextField'
type Props = TextFieldProps & {
hideHelperText?: boolean;
};
class PasswordInput extends React.Component<Props> {
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
/** do stuff */
};
render() {
const {
hideHelperText,
classes,
...rest
} = this.props;
return (
<React.Fragment>
<TextField
/** errors out here */
/*
Type 'HideShowText | null' is not assignable to type 'HTMLDivElement | null'.
Type 'HideShowText' is missing the following properties from type 'HTMLDivElement':
align, addEventListener, removeEventListener, accessKey, and 238 more
*/
{...rest}
onChange={this.onChange}
/>
{!hideHelperText && 'hello world'}
</React.Fragment>
);
}
}
export default PasswordInput as React.ComponentType<Props>;;
Odgovor #2
Sinoć sam naišao na ovu točnu pogrešku. Radim isti tip unije na drugim mjestima, poput SelectProps, bez problema, ali TextFieldProps je problematičan na više svojstava, a StandardTextFieldProps samo na ref. Stoga, kao privremena mjera, mogli biste deklarirati:
export type MyTextFieldProps = Omit< StandardTextFieldProps, 'ref' > & { ... }
