项目作者: sbdchd

项目描述 :
:cake: TSLint rules for sweet code
高级语言: TypeScript
项目地址: git://github.com/sbdchd/tslint-cake.git
创建时间: 2019-01-18T03:47:31Z
项目社区:https://github.com/sbdchd/tslint-cake

开源协议:

下载


tslint-cake npm version CircleCI

TSLint rules for sweet code

Usage

  1. Install
  1. yarn add tslint-cake
  1. Update tslint.json
  1. {
  2. "extends": ["tslint-cake"],
  3. "rules": {
  4. "react-prefer-simple-fragment": true
  5. // ...
  6. }
  7. }

Why?

To have a place to add miscellaneous TSLint rules that don’t exist in TSLint
or common TSLint libraries.

Rules

no-pointless-computed-property-name

Use { foo: bar } instead of { ["foo"]: bar }

react-prefer-simple-fragment [Fixer]

Use <></> instead of <React.Fragment><React.Fragment></React.Fragment>

jsx-no-true-attribute [Fixer]

Use <Foo bar></Foo> instead of <Foo bar={true}></Foo>

no-template-string-cast

Prefer String() or .toString() to cast as a string instead of `${}` .

no-pointless-case-scope

Remove unnecessary scopes in switch statement cases when the only child
expression is a return statement.

E.g.,

  1. switch (foo) {
  2. case bar: {
  3. return "foo"
  4. }
  5. }
  6. // can become
  7. switch (foo) {
  8. case bar:
  9. return "foo"
  10. }

no-name-never

Using a variable name with type never is likely a mistake.

name is defined globally if you include --lib dom.

see: https://github.com/Microsoft/TypeScript/blob/3a2f6a3ed1a598a241e7c750873105f22e7a2463/lib/lib.dom.d.ts#L17405

improper-map-prefer-foreach

Prefer forEach instead of map when the result isn’t used

  1. foo.map(x => {
  2. x.id = 10
  3. })
  4. // should be
  5. foo.forEach(x => {
  6. x.id = 10
  7. })

no-promise-catch

Using .catch() on a Promise usually means that you could better describe
the outputs of the async function using a union or Result<T, E> types.

  1. declare const getFooAsync: () => Promise<number>
  2. getFooAsync()
  3. .then(r => console.log(r))
  4. .catch(e => console.error(e)) // `e` could be anything. We can't type the arg to catch.
  5. // instead we can do the following
  6. declare const getBarAsync: () => Promise<number | Error>
  7. getBarAsync().then(r => {
  8. if (r instanceof Error) {
  9. console.error(r)
  10. } else {
  11. console.log(r)
  12. }
  13. })

object-index-must-return-possibly-undefined

The values of an index signature of a type are always possibly undefined
even though TypeScript won’t warn you. This lint forces you to define your
index signature to possibly return undefined.

  1. interface IFoo {
  2. [key: string]: number // Error: Value of an object key is possibly undefined.
  3. }
  4. interface IBar {
  5. [key: string]: number | undefined // ok
  6. }

exact-object-spread

This rule is an attempt at gaining some semblence of
exactness with object
spread.

Currently, there are cases where TypeScript won’t warn about adding extra,
non-existing properties to an object when spreading. This lint fills in some
of those gaps and warns you when adding non-existent properties.

Note, this rule attempts to enforce
exactness on
all spreads and this might not be what you want.

  1. interface IState {
  2. id: number
  3. name: string
  4. address: {
  5. street: string
  6. state: string
  7. country: string
  8. }
  9. }
  10. function update(state: IState): IState {
  11. return {
  12. ...state,
  13. notProp: false // TypeScript error
  14. }
  15. }
  16. // TypeScript will also warn with nested spreading
  17. function update(state: IState): IState {
  18. return {
  19. ...state,
  20. address: {
  21. ...state.address,
  22. notProp: false // TypeScript error
  23. }
  24. }
  25. }
  26. // However, if we pull the nested spread out into a variable TypeScript won't
  27. // warn us about extra properties
  28. // no errors with TypeScript
  29. function update(state: IState): IState {
  30. const address = {
  31. // TSLint error when we enable this rule
  32. ...state.address,
  33. foo: "bar"
  34. }
  35. return {
  36. ...state,
  37. address
  38. }
  39. }

react-memo-requires-custom-compare

When using React.memo() or extends React.PureComponent the default
comparsions are shallow which means they will always render for complex props
like Date‘s, Arrays, or Objects, even if the underlying values are equivalent.

In the cases of these complex props, this lint will warn you and recommend
passing a custom compare function React.memo() or defining a custom
shouldComponentUpdate and extending React.Component.

Caveat: If an object is passed as a prop and isn’t copied/changed, i.e., no
{...x} then referential integrity is retained and the shallow compare of
React.memo() and PureComponent will correctly prevent a render. So if you
are using something like
Immutable-js where shallow
equals is maintained then this lint might be less helpful.

  1. interface IOkayProps {
  2. name: string
  3. accountAge: number | string
  4. admin: boolean
  5. }
  6. const Okay = React.memo((props: IOkayProps) => (
  7. <p>
  8. {props.name} ({props.accountAge})
  9. </p>
  10. ))
  11. interface IBadProps {
  12. user: {
  13. name: string
  14. }
  15. }
  16. // TSLint raises error
  17. const Bad = React.memo((props: IBadProps) => <p>{props.user.name} </p>)
  18. // TSLint raises error
  19. class BadPure extends React.PureComponent<IBadProps> {
  20. render() {
  21. return <p>{props.user.name} </p>
  22. }
  23. }

no-implicit-to-string

Checks for cases where null, undefined, or object are converted to
string.

  1. const userName: string | null | Date = null
  2. // all of the following error
  3. const foo = `hello ${userName}`
  4. const bar = String(userName)
  5. const blah = "hello " + userName

Dev

  1. yarn build
  2. yarn test
  3. yarn lint
  4. yarn fmt
  5. yarn publish

TODO

  • add fixers