我知道TypeScript定义文件可以帮助我们在TypeScript中使用代码的JavaScript版本。但是我试图理解React组件的TypeScript定义文件。这些问题是面试官提出的,我不知道这些问题的答案。但是我想知道。该组件是用JavaScript编写的,但也有Typescript定义文件。
Button.js:
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { mapToCssModules, tagPropType } from './utils';
const propTypes = {
active: PropTypes.bool,
'aria-label': PropTypes.string,
block: PropTypes.bool,
color: PropTypes.string,
disabled: PropTypes.bool,
outline: PropTypes.bool,
tag: tagPropType,
innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func, PropTypes.string]),
onClick: PropTypes.func,
size: PropTypes.string,
children: PropTypes.node,
className: PropTypes.string,
cssModule: PropTypes.object,
close: PropTypes.bool,
};
const defaultProps = {
color: 'secondary',
tag: 'button',
};
class Button extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick(e) {
if (this.props.disabled) {
e.preventDefault();
return;
}
if (this.props.onClick) {
this.props.onClick(e);
}
}
render() {
let {
active,
'aria-label': ariaLabel,
block,
className,
close,
cssModule,
color,
outline,
size,
tag: Tag,
innerRef,
...attributes
} = this.props;
if (close && typeof attributes.children === 'undefined') {
attributes.children = <span aria-hidden>×</span>;
}
const btnOutlineColor = `btn${outline ? '-outline' : ''}-${color}`;
const classes = mapToCssModules(classNames(
className,
{ close },
close || 'btn',
close || btnOutlineColor,
size ? `btn-${size}` : false,
block ? 'btn-block' : false,
{ active, disabled: this.props.disabled }
), cssModule);
if (attributes.href && Tag === 'button') {
Tag = 'a';
}
const defaultAriaLabel = close ? 'Close' : null;
return (
<Tag
type={(Tag === 'button' && attributes.onClick) ? 'button' : undefined}
{...attributes}
className={classes}
ref={innerRef}
onClick={this.onClick}
aria-label={ariaLabel || defaultAriaLabel}
/>
);
}
}
Button.propTypes = propTypes;
Button.defaultProps = defaultProps;
export default Button;
Button.d.ts:
import * as React from 'react';
import { CSSModule } from '../index';
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
[key: string]: any;
outline?: boolean;
active?: boolean;
block?: boolean;
color?: string;
disabled?: boolean;
tag?: string | React.ReactType;
innerRef?: React.Ref<HTMLButtonElement>;
onClick?: React.MouseEventHandler<any>;
size?: any;
id?: string;
style?: React.CSSProperties;
cssModule?: CSSModule;
}
declare class Button<T = {[key: string]: any}> extends React.Component<ButtonProps> {}
export default Button;
在Button.d.ts
文件中,有一个interface
但是
界面中indexable-type
[key: string]: any;
的用途是什么?和
为什么declare class Button<T = {[key: string]: any}>
是用Generic编写的。另外,此组件的JavaScript版本还有2个附加的props
。
children: PropTypes.node,
className: PropTypes.string,
但是为什么接口不包含这两个props
的类型声明?
答案 0 :(得分:1)
正如您所说的“打字稿定义文件可帮助我们在打字稿中使用javascript版本的代码”,这正是在这里完成的工作。
您的组件是使用Vanilla JS编写的,因此该组件没有类型。这意味着,当您使用<Button/>
之类的组件时,其类型将为 any ,并且Typescript无法推断需要传递给该组件的道具是什么。
此定义文件的作用是声明该组件的props类型,并将其通过泛型传递给React.Component类。但是我不知道他为什么要声明这个通用的T = {[key: string]: any}
,这将需要更深入的分析,或者仅仅是实现错误。
然后将在运行时中使用react propTypes 对象来检查您是否传递了正确的消息,但打字稿将完全忽略它。此外,所有打字稿代码都将被转换为Vanilla JS,这意味着打字稿将在运行时不进行任何类型检查。
“此组件的javascript版本具有2个其他道具”
也许这些道具已经存在于他正在扩展的父组件中:React.ButtonHTMLAttributes