Reputation: 715
Once I started to use Typescript
in React
I notice one thing I don't like which is to the need to declare every props to a component. Before this we can use {...props}
but now I have to declare in interface every single native props
like ref
, placeholder
, defaultValue
etc.
interface InputProps {
customProp: boolean;
props: any;
}
const Input = ({ customProp, placeholder, ...props }: InputProps) => {
//warning
return <input type="text" {...props} />;
};
https://codesandbox.io/s/distracted-burnell-vlt3i?file=/src/App.tsx
I want to enjoy the old day where I only need to declare non-native prop in the interface, possible? the native props has been passed via {...props}
Upvotes: 1
Views: 936
Reputation: 42556
If you are working with TypeScript, the best practice would be to strictly define the interfaces/type aliases of your props for each component. For your case of the Input
component, the correct interface would be
interface InputProps {
customProp: boolean;
placeholder: string;
// add other props below
}
That being said, interfaces and type aliases can be exported, shared, and extended, thus this will reduce the amount of repeated code. For instance,
interface OtherInputProps extends InputProps {
value: string;
}
Of course, you can do something like [key:string]: any
, but that would totally defeat the purpose of using TypeScript, as you are essentially ignoring the typechecking capabilities of TypeScript. In that case, t will be less verbose, to revert back to JavaScript.
Edit: Just realised that OP is trying to extend the input props with additional props. In that case, the correct base type to use would be `React.InputHTMLAttributes:
export interface InputProps extends React.InputHTMLAttributes< HTMLInputElement> {
customProp: boolean;
}
or
type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
customProp: boolean;
}
Upvotes: 1
Reputation: 85062
I want to enjoy the old day where I only need to declare non-native prop in the interface, possible?
Yes, it's possible. Typescript allows interfaces to extend from others, so you can define your interface to have all the things that input elements expect, plus your custom prop:
export interface ExampleProps extends React.HTMLProps<HTMLInputElement> {
customProp: boolean;
}
const Example: React.FC<ExampleProps> = ({ customProp, placeholder, ...rest }) => {
const { t } = useTranslation();
return <input type="text" {...rest} />;
};
With this definition, it's legal for me to try to render the following:
const Thing: FC = () => {
return <Example placeholder="foo" customProp={true} defaultValue="3" />;
};
But typescript will point out if, for example, i fail to pass in custom prop, or if i pass in an object for the placholder.
Upvotes: 1
Reputation: 10264
import * as React from "react";
import "./styles.css";
interface InputProps {
customProp: boolean;
// props: any; // I think it doesn't need to you.
[key:string]: any;
}
const Input = ({ customProp, placeholder, ...props }: InputProps) => {
return <input type="text" {...props} />;
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Input hello="hello" customProp={false} placeholder={"name"} />
</div>
);
}
You can enjoy your old day with [key:string]: any
.
But, I don't want to recommend to use [key:string]: any
.
because it makes no meaning with typescript
.
and, In my opinion, If you get stressed with typescript
, you can use js
instead.
Upvotes: 2