在写组件时经常会遇到这么一种情况,比如写一个MyInput组件
<MyInput type="text" name="input" id="input" onInput={()=>alert('input')}/>
像例子中的type,name,id,onInput都是html的原生属性,在React+ts中需要通过interface定义才能传递,但是一个一个定义太麻烦了,有没有简单的方法呢。
原生属性的继承
其实在React中已经定义好了原生html属性的接口了,通过React.InputHTMLAttributes就可以把原生属性都继承过来,具体如下
import React from 'React';
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
export const MyInput: React.FC<InputProps> = (props) => {
return (
<input
{...props}
/>
)
};
这里只举例input,其他的比如button就继承React.ButtonHTMLAttributes<HTMLButtonElement>具体可以在
node_modules\@types\react\index.d.ts 里看到
原生属性的重写
原生属性的重写需要用到typescript内置的泛型工具Omit,它的作用是可以排除某几个属性。比如我想重新定义type的属性,就可以这样写
import React from 'React';
const tuple = <T extends string[]>(...args: T) => args;
const InputTypes = tuple('typeA','typeB','typeC');
export type InputType = typeof InputTypes[number];
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>,'type'> { // 代表继承除type外是所有的input属性
type: InputType
}
然后可以使用rc-uitl工具把传过来的props中的type删掉,赋给原生input,完整代码
import React from 'React';
import omit from 'rc-util/lib/omit';
const tuple = <T extends string[]>(...args: T) => args;
const InputTypes = tuple('typeA','typeB','typeC');
export type InputType = typeof InputTypes[number];
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>,'type'> {
type: InputType
}
export const MyInput: React.FC<InputProps> = (props) => {
const { type } = props
// todo 处理type
const other = omit(props,['type']) //删除props中的type
return (
<input
{...other}
/>
)
};