-
-
Notifications
You must be signed in to change notification settings - Fork 54.2k
Feat/use eslint to lint typescript #15236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
3db532a to
1b45d88
Compare
1b45d88 to
94924fd
Compare
|
草稿中,有问题和需求可以告诉我。 |
|
Deploy preview for ant-design ready! Built with commit 3db532a425d8f3010eda4a63a92a58e983881704 |
|
Deploy preview for ant-design ready! Built with commit 94924fd |
| 'no-return-assign': 1, | ||
| 'no-plusplus': 1, | ||
| 'react/no-access-state-in-setstate': 1, | ||
| 'react/no-multi-comp': 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
感觉还是 airbnb 的规则更全一点,这里还要自己维护 rules 列表。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eslint-config-umi 是基于 airbnb 的,所以报了大量 error, 我将这部分 error 临时改成了 warning,其中很多的确是不规范的习惯可能要改,另外一些是可以忽略的。
扫了一下大概 2000 多个= =;
另外,我把这部分规则注释一下吧,便于理解,大家一起看下哪些要改哪些忽略。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
不要改 warning,要么 error 要么去掉。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ci还是可靠吧😂,这么大一项目,我怕改出问题。那我就按错误一个一个改,大家帮我cr下😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
不着急改,先放出来看看哪些 errors,改动尽量少最好。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
另外 eslint-config-umi 貌似不是基于 airbnb 的。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
之前不是,我发了一个2.0beta,基于airbnb,并支持了ts。我想通过pro或者antd把规则沉到eslint-config-umi,然后我们内部也可以用。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我把这些error配合代码整理一下发出来。
ant design eslint 规则探索
getSelectedKeysName(direction: TransferDirection) {
return direction === 'left' ? 'sourceSelectedKeys' : 'targetSelectedKeys';
}
建议:
function getShowDateFromValue(value: RangePickerValue) {
const [start, end] = value;
// value could be an empty array, then we should not reset showDate
if (!start && !end) {
return;
}
const newEnd = end && end.isSame(start, 'month') ? end.clone().add(1, 'month') : end;
return [start, newEnd] as RangePickerValue;
}
建议:
let enquire: any;
if (typeof window !== 'undefined') {
...
window.matchMedia = window.matchMedia || matchMediaPolyfill;
enquire = require('enquire.js');
}
建议:
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
if (typeof window !== 'undefined') {
...
window.matchMedia = window.matchMedia || matchMediaPolyfill;
}
import * as React from 'react';建议:
建议:
import * as React from 'react';
import { createElement, Component } from 'react';
直接合并成一条语句 import React, { createElement, Component } from 'react';建议:
建议:
建议:
建议:
建议:
class Title extends React.Component<SkeletonTitleProps, any> {
render() {
const { prefixCls, className, width, style } = this.props;
return <h3 className={classNames(prefixCls, className)} style={{ width, ...style }} />;
}
}
建议:
建议:
建议:
if (!!loading) {
return;
}
建议:
switch (size) {
case 'large':
sizeCls = 'lg';
break;
case 'small':
sizeCls = 'sm';
default:
break;
}
建议:
if (menuMode === 'horizontal') {
menuOpenAnimation = 'slide-up';
} else if (menuMode === 'inline') {
menuOpenAnimation = animation;
} else {
// When mode switch from inline
// submenu should hide without animation
if (this.switchingModeFromInline) {
menuOpenAnimation = '';
this.switchingModeFromInline = false;
} else {
menuOpenAnimation = 'zoom-big';
}
}
建议:
Modal.warning = Modal.warn = function(props: ModalFuncProps) {
const config = {
type: 'warning',
icon: <Icon type="exclamation-circle" />,
okCancel: false,
...props,
};
return confirm(config);
};建议:
React.cloneElement(ele, {
className: classNames([
ele.props.className,
!reverse && !!pending
? idx === itemsCount - 2
? lastCls
: ''
: idx === itemsCount - 1
? lastCls
: '',
mode === 'alternate'
? idx % 2 === 0
? `${prefixCls}-item-left`
: `${prefixCls}-item-right`
: mode === 'right'
? `${prefixCls}-item-right`
: '',
]),
}),
建议:
onSuccess = (response: any, file: UploadFile) => {
this.clearProgressTimer();
try {
if (typeof response === 'string') {
response = JSON.parse(response);
}
} catch (e) {
/* do nothing */
}
}
建议:
export default function wrapperRaf(callback: () => void, delayFrames: number = 1): number {
const myId: number = id++;
let restFrames: number = delayFrames;
function internalCallback() {
restFrames -= 1;
if (restFrames <= 0) {
callback();
delete ids[id];
} else {
ids[id] = raf(internalCallback);
}
}
ids[id] = raf(internalCallback);
return myId;
}
建议:
if (definingProperty || this === target.prototype || this.hasOwnProperty(key)) {
return fn;
}
建议:
const isNumeric = (value: any): boolean => {
return !isNaN(parseFloat(value)) && isFinite(value);
};
建议:error,数量:3
建议:
let dangerousTheme: ThemeType | undefined = undefined;
建议:
建议:
const resultListMatchInputWidth = showSearch.matchInputWidth === false ? false : true;
建议:
建议:
export const svgBaseProps = {
width: '1em',
height: '1em',
fill: 'currentColor',
['aria-hidden']: 'true',
focusable: 'false',
};
建议:
warning(
!overlayProps.mode || overlayProps.mode === 'vertical',
'Dropdown',
`mode="${overlayProps.mode}" is not supported for Dropdown\'s Menu.`,
);
建议:
close = (e: EventType) => {
if (this.props.visible !== undefined) {
if (this.props.onClose) {
this.props.onClose(e);
}
return;
}
};
建议:
建议:
return api.open({ content, duration: duration, type, onClose });
建议:
if (boxSizing === 'border-box') {
// border-box: add border, since height = content + padding + border
height = height + borderSize;
} else if (boxSizing === 'content-box') {
// remove padding, since height = content
height = height - paddingSize;
}
建议:
const fileList = this.state.fileList;
建议:
onChange.apply(
null,
this.prepareParamsArguments({
...this.state,
selectionDirty: false,
filters,
pagination,
}),
);
const params = this.prepareParamsArguments({
...this.state,
selectionDirty: false,
filters,
pagination,
});
onChange(...params);建议:
const orientationPrefix = orientation.length > 0 ? '-' + orientation : orientation;建议:
<button onClick={this.close} aria-label="Close" className={`${prefixCls}-close`}>
<Icon type="close" />
</button>
建议:
static defaultProps = {
loading: false,
ghost: false,
block: false,
};
static propTypes = {
type: PropTypes.string,
shape: PropTypes.oneOf(ButtonShapes),
size: PropTypes.oneOf(ButtonSizes),
htmlType: PropTypes.oneOf(ButtonHTMLTypes),
onClick: PropTypes.func,
loading: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
className: PropTypes.string,
icon: PropTypes.string,
block: PropTypes.bool,
};
建议:
if (this.props.listType !== 'picture' && this.props.listType !== 'picture-card') {
return;
}
建议: 建议:
const closeIcon = (
<span className={`${prefixCls}-close-x`}>
<Icon className={`${prefixCls}-close-icon`} type={'close'} />
</span>
);
建议:
建议:
<Dialog
prefixCls={prefixCls}
className={classString}
wrapClassName={classNames({ [`${contentPrefixCls}-centered`]: !!props.centered })}
onCancel={close.bind(this, { triggerCancel: true })}
visible={visible}
...
>
...
</Dialog>
建议:
belowShowChange = () => {
this.setState({ belowShow: !this.state.belowShow });
};
建议:
const rowList = [...Array(rows)].map((_, index) => (
<li key={index} style={{ width: this.getWidth(index) }} />
));
建议:
let currentContent = content;
function wrap(needed: boolean | undefined, tag: string) {
if (!needed) return;
currentContent = React.createElement(tag, {
children: currentContent,
});
}
建议:
componentDidUpdate(prevProps: ButtonProps) {
...
const { loading } = this.props;
if (loading && typeof loading !== 'boolean' && loading.delay) {
this.delayTimeout = window.setTimeout(() => this.setState({ loading }), loading.delay);
} else if (prevProps.loading === this.props.loading) {
return;
} else {
this.setState({ loading });
}
}
建议:
componentDidMount() {
const NO_FLEX = ' no-flex';
const tabNode = ReactDOM.findDOMNode(this) as Element;
if (tabNode && !isFlexSupported && tabNode.className.indexOf(NO_FLEX) === -1) {
tabNode.className += NO_FLEX;
}
}
建议:
建议:
建议:
static defaultProps = {
dataSource: [],
render: noop as TransferRender,
locale: {},
showSearch: false,
};
static propTypes = {
prefixCls: PropTypes.string,
disabled: PropTypes.bool,
...
}
建议:
建议:
/** 是否支持选中 */
checkable?: boolean;
建议: export interface UploadChangeParam {
file: UploadFile;
fileList: Array<UploadFile>;
event?: { percent: number };
}
建议:
export interface UploadListProps {
progressAttr?: Object;
}
建议: import zh_CN from '../../date-picker/locale/zh_CN';
建议:
建议:
建议: interface ParagraphProps extends BlockProps {}
建议:
let id: number = 0;
建议:
建议: const state = {} as WeekPickerState;
建议:
建议:
export type ValidationRule = {
/** validation error message */
message?: React.ReactNode;
/** built-in validation type, available options: https://github.com/yiminghe/async-validator#type */
type?: string;
/** indicates whether field is required */
required?: boolean;
/** treat required fields that only contain whitespace as errors */
whitespace?: boolean;
}
建议: |
|
先整理 20个,持续整理。 |
问题原因出现这些问题的原因是,之前的 如何做大家可以看一下,如果没有异议,我会将需要修复的错误分成大概5份,大家认领修复。待议 其他定下来的规则,可以下沉到 |
|
阿里可以维护一个开源项目通用的规则仓库 |
蚂蚁现在维护的: |







首先,感谢你的贡献!😄
新特性请提交至 feature 分支,其余可提交至 master 分支。
在一个维护者审核通过后合并。
请确保填写以下 pull request 的信息,谢谢!~
🤔 这个变动的性质是?
👻 需求背景
lint 统一是趋势,使用 eslint 来检查有更完善的规则,发现更多的习惯问题。
💡 解决方案和最终实现是?
实现
混合检查 js 和 ts,目前社区没有看到很优雅的方案,暂时通过 override 的方式实现。
待讨论和解决的问题
📝 更新日志怎么写?
use eslint to lint typescript
☑️ 请求合并前的自查清单