ESLint 修改点整理
ESLint 为团队和项目带来的益处,这里不多说,本文主要是个人近期修改项目代码一些错误修改整理的内容。
备注:尽量使用默认 Prettier 规则,根据实际情况略有调整。项目技术栈 React, Redux, Redux-Sagas, TypeScript。
Plugin 列表
"plugin:react/recommended""plugin:@typescript-eslint/recommended""prettier/@typescript-eslint""plugin:prettier/recommended"
ERROR List
-
[Error] eslint@typescript-eslint/ban-ts-comment
Do not use "// @ts-nocheck" because it alters compilation errors. Desc link
TypeScript 提供
@ts-expect-error @ts-ignore @ts-nocheck @ts-check指令注释方式,用来改变 tsc 编译时处理文件的方式,如果大量使用此类注释影响 TypeScript 的特性,既然使用 ts 就要拥抱它的特性,lint 中默认对no-check会按照error进行提示;可以根据实际情况调整规则,改为warn。 -
[Error] @typescript-eslint/ban-types
补充提示:
Don't use `{}` as a type. `{}` actually means "any non-nullish value".
- If you want a type meaning "any object", you probably want `Record<string, unknown>` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.
-
[Error] react/jsx-no-target-blank
出于安全考虑,React 中产生新打开页面的链接,需要增加
rel='noreferrer'用来保护原站。具体说明详见:Link
WARN List
-
[Warn] Missing return type on function.eslint@typescript-eslint/explicit-module-boundary-types
desc link 说明:针对函数的定义,建议每一个函数都要显式的表明函数返回值。这在
*.jsx, *.tsx文件中,React 生命周期函数都提示,可以使用 eslint overrides 规则,只针对*.js, *.ts生效。
{
"rules": {
// disable the rule for all files
"@typescript-eslint/explicit-module-boundary-types": "off"
},
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.js", "*.ts"],
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "warn"
}
}
]
}
- [Warn] @typescript-eslint/no-unused-vars
应该是最经常遇到的一个警告,定义了变量,下文没有使用。
个人建议:非关键算法或逻辑代码,当你阅读时没用,就删掉吧,可以保留注释,因为即使你想保留这段代码,以备不时之需,但是真到需要用到代码你再次阅读的时候,实现思路以及上下文联系可能已经相差很远。
Prettier 细节
- 关于默认逗号的变化 link
Prettier 自动 v2.0.0 开始,将 trailingComma 默认配置由 none 改为 es5,在我看来是一种很好的方式。
举个例子,当 import 多个内容、一个对象需要增加属性、一个数组追加元素,如果默认已经追加了逗号,那么就可以直接追加,而不必要移动光标去前一行手动增加一个逗号,这样就增加了一些便利性,与此同时便于快速定位甚至避免由于一个逗号的引起的错误。
TS2322 自定义属性
import { AriaAttributes, DOMAttributes } from "react";
declare module "react" {
interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
// extends React's HTMLAttributes
custom?: string;
}
}
TS2679
问题实例片段代码:
function* loadSimilar(skuId: string) {
yield put({
type: ActionTypes.REQUEST_SIMILAR.PENDING,
});
try {
const { data } = yield API.querySimilar(skuId);
yield put({
type: ActionTypes.REQUEST_SIMILAR.SUCCESS,
data,
});
} catch (error) {
yield put({
type: ActionTypes.REQUEST_SIMILAR.FAILURE,
});
}
}
function* watchSimilar() {
yield takeEvery(ActionTypes.LOAD_SIMILAR, loadSimilar);
}
修改后代码:
- function* loadSimilar(skuId: string) {
+ function* loadSimilar({ skuId }: { type: string; skuId: string }) {
yield put({
type: ActionTypes.REQUEST_SIMILAR.PENDING,
});
try {
const { data } = yield API.querySimilar(skuId);
yield put({
type: ActionTypes.REQUEST_SIMILAR.SUCCESS,
data,
});
} catch (error) {
yield put({
type: ActionTypes.REQUEST_SIMILAR.FAILURE,
});
}
}
function* watchSimilar() {
yield takeEvery(ActionTypes.LOAD_SIMILAR, loadSimilar);
}
解答:Redux-Saga 中 takeEvery 第二个参数是一个 action,所以定义 loadSimilar 时候需要遵循 TakeableChannel<unknown> ,定义 type。
参考:stackoverflow.com/a/60558041
切记,保证一路传递参数变量匹配,否则会出现无法赋值问题,例如下面代码:
- function* cartOptCheckOne({ param }: { type: string; param: any }) {
+ function* cartOptCheckOne({
+ // type = ActionTypes.OPT_CARTCHECKONE,
+ RequestParam,
+ }: {
+ type: string;
+ RequestParam: any;
+ }) {
外层触发 action 传参数代码如下:
this.props.optCartCheckOne({
RequestParam: requestParam,
});
如果定义 cartOptCheckOne 使用 param 就会导致传递过程中因为变量名称不同无法解构,导致传参中断。
ESLint Config
参考 www.robertcooper.me/using-eslin…
原文链接:BLOG