You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -60,23 +61,32 @@ Below is some information about the `readonly` modifier and the benefits of usin
60
61
You might think that using `const` would eliminate mutation from your TypeScript code. **Wrong.** Turns out that there's a pretty big loophole in `const`.
61
62
62
63
```typescript
63
-
interfacePoint { x:number, y:number }
64
+
interfacePoint {
65
+
x:number;
66
+
y:number;
67
+
}
64
68
const point:Point= { x: 23, y: 44 };
65
69
point.x=99; // This is legal
66
70
```
67
71
68
72
This is why the `readonly` modifier exists. It prevents you from assigning a value to the result of a member expression.
This is just as effective as using Object.freeze() to prevent mutations in your Redux reducers. However the `readonly` modifier has **no run-time cost**, and is enforced at **compile time**. A good alternative to object mutation is to use the ES2016 object spread [syntax](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#object-spread-and-rest) that was added in typescript 2.1:
83
+
This is just as effective as using Object.freeze() to prevent mutations in your Redux reducers. However the `readonly` modifier has **no run-time cost**, and is enforced at **compile time**. A good alternative to object mutation is to use the ES2016 object spread [syntax](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#object-spread-and-rest) that was added in typescript 2.1:
This rule should be combined with tslint's built-in `no-var-keyword` rule to enforce that all variables are declared as `const`.
159
186
160
187
There's no reason to use `let` in a Redux/React application, because all your state is managed by either Redux or React. Use `const` instead, and avoid state bugs altogether.
@@ -166,69 +193,82 @@ let x = 5; // <- Unexpected let or var, use const.
166
193
What about `for` loops? Loops can be replaced with the Array methods like `map`, `filter`, and so on. If you find the built-in JS Array methods lacking, use [ramda](http://ramdajs.com/), or [lodash-fp](https://github.com/lodash/lodash/wiki/FP-Guide).
167
194
168
195
```typescript
169
-
const SearchResults =
170
-
({ results }) =>
171
-
<ul>{
172
-
results.map(result=> <li>result</li>) // <- Who needs let?
173
-
}</ul>;
196
+
const SearchResults = ({ results }) => (
197
+
<ul>
198
+
{results.map(result=> <li>result</li>) // <- Who needs let?
This rule prohibits syntax that mutates existing objects via assignment to or deletion of their properties. While requiring the `readonly` modifier forces declared types to be immutable, it won't stop assignment into or modification of untyped objects or external types declared under different rules. Forbidding forms like `a.b = 'c'` is one way to plug this hole. Inspired by the no-mutation rule of [eslint-plugin-immutable](https://github.com/jhusain/eslint-plugin-immutable).
196
230
197
231
```typescript
198
-
const x = {a: 1};
232
+
const x = {a: 1};
199
233
200
-
x.foo='bar'; // <- Modifying properties of existing object not allowed.
234
+
x.foo="bar"; // <- Modifying properties of existing object not allowed.
201
235
x.a+=1; // <- Modifying properties of existing object not allowed.
202
236
deletex.a; // <- Modifying properties of existing object not allowed.
There are two ways function members can be declared in an interface or type alias:
221
260
222
261
```typescript
223
262
interfaceZoo {
224
-
foo():string,// MethodSignature, cannot have readonly modifier
225
-
readonly bar: () =>string,// PropertySignature
263
+
foo():string;// MethodSignature, cannot have readonly modifier
264
+
readonly bar: () =>string;// PropertySignature
226
265
}
227
266
```
228
267
229
268
The `MethodSignature` and the `PropertySignature` forms seem equivalent, but only the `PropertySignature` form can have a `readonly` modifier. Becuase of this any `MethodSignature` will be mutable. Therefore the `no-method-signature` rule disallows usage of this form and instead proposes to use the `PropertySignature` which can have a `readonly` modifier. It should be noted however that the `PropertySignature` form for declaring functions does not support overloading.
230
269
231
270
### no-delete
271
+
232
272
The delete operator allows for mutating objects by deleting keys. This rule disallows any delete expressions.
233
273
234
274
```typescript
@@ -238,58 +278,62 @@ delete object.property; // Unexpected delete, objects should be considered immut
238
278
As an alternative the spread operator can be used to delete a key in an object (as noted [here](https://stackoverflow.com/a/35676025/2761797)):
Thanks to libraries like [recompose](https://github.com/acdlite/recompose) and Redux's [React Container components](http://redux.js.org/docs/basics/UsageWithReact.html), there's not much reason to build Components using `React.createClass` or ES6 classes anymore. The `no-this` rule makes this explicit.
248
289
249
290
```typescript
250
291
const Message =React.createClass({
251
292
render: function() {
252
-
return <div>{this.props.message}</div>; // <- no this allowed
293
+
return <div>{this.props.message}</div>; // <- no this allowed
253
294
}
254
-
})
295
+
});
255
296
```
297
+
256
298
Instead of creating classes, you should use React 0.14's [Stateless Functional Components](https://medium.com/@joshblack/stateless-components-in-react-0-14-f9798f8b992d#.t5z2fdit6) and save yourself some keystrokes:
What about lifecycle methods like `shouldComponentUpdate`? We can use the [recompose](https://github.com/acdlite/recompose) library to apply these optimizations to your Stateless Functional Components. The [recompose](https://github.com/acdlite/recompose) library relies on the fact that your Redux state is immutable to efficiently implement shouldComponentUpdate for you.
Mixing functions and data properties in the same interface is a sign of object-orientation style. This rule enforces that an inteface only has one type of members, eg. only data properties or only functions.
280
322
281
323
### no-expression-statement
324
+
282
325
When you call a function and don’t use it’s return value, chances are high that it is being called for its side effect. e.g.
283
326
284
327
```typescript
285
-
array.push(1)
286
-
alert('Hello world!')
328
+
array.push(1);
329
+
alert("Hello world!");
287
330
```
288
331
289
332
This rule checks that the value of an expression is assigned to a variable and thus helps promote side-effect free (pure) functions.
@@ -306,11 +350,12 @@ This rule checks that the value of an expression is assigned to a variable and t
306
350
```
307
351
308
352
### no-if-statement
353
+
309
354
If statements is not a good fit for functional style programming as they are not expresssions and do not return a value. This rule disallows if statements.
310
355
311
356
```typescript
312
357
let x;
313
-
if(i===1) {
358
+
if(i===1) {
314
359
x=2;
315
360
} else {
316
361
x=3;
@@ -325,6 +370,27 @@ const x = i === 1 ? 2 : 3;
325
370
326
371
For more background see this [blog post](https://hackernoon.com/rethinking-javascript-the-if-statement-b158a61cd6cb) and discussion in [#54](https://github.com/jonaskello/tslint-immutable/issues/54).
327
372
373
+
### no-for-statement
374
+
375
+
In functional programming we want everthing to be an expression that returns a value. The `for` statement is not an expression. This rule disallows for statements, including `for of` and `for in`.
376
+
377
+
```typescript
378
+
const numbers = [1, 2, 3];
379
+
const double = [];
380
+
for (let i =0; i<numbers.length; i++) {
381
+
double[i] =numbers[i] *2;
382
+
}
383
+
```
384
+
385
+
Instead consider using `map` or `reduce`:
386
+
387
+
```typescript
388
+
const numbers = [1, 2, 3];
389
+
const double =numbers.map(n=>n*2);
390
+
```
391
+
392
+
For more background see this [blog post](https://hackernoon.com/rethinking-javascript-death-of-the-for-loop-c431564c84a8) and discussion in [#54](https://github.com/jonaskello/tslint-immutable/issues/54).
393
+
328
394
## Options
329
395
330
396
### Using the `ignore-local` option
@@ -337,9 +403,11 @@ The quote above is from the [clojure docs](https://clojure.org/reference/transie
337
403
Note that using this option can lead to more imperative code in functions so use with care!
338
404
339
405
### Using the `ignore-class` option
406
+
340
407
Doesn't check for `readonly` in classes.
341
408
342
409
### Using the `ignore-interface` option
410
+
343
411
Doesn't check for `readonly` in interfaces.
344
412
345
413
### Using the `ignore-prefix` option
@@ -357,8 +425,8 @@ Typescript is not immutable by default but it can be if you use this package. So
357
425
358
426
```typescript
359
427
typeperson= {
360
-
readonly name:string,
361
-
mutableAge:number// This is OK with ignore-prefix = "mutable"
428
+
readonly name:string;
429
+
mutableAge:number;// This is OK with ignore-prefix = "mutable"
0 commit comments