Skip to content

Commit 5934d7d

Browse files
committed
null is bad
1 parent 4bf7fe1 commit 5934d7d

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
* [Classes are Useful](docs/tips/classesAreUseful.md)
5757
* [Avoid Export Default](docs/tips/defaultIsBad.md)
5858
* [Limit Property Setters](docs/tips/propertySetters.md)
59+
* [`null` is bad](docs/tips/nullIsBad.md)
5960
* [StyleGuide](docs/styleguide/styleguide.md)
6061
* [Common Errors](docs/errors/main.md)
6162
* [TypeScript Compiler Internals](docs/compiler/overview.md)

docs/tips/nullIsBad.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Null is Bad
2+
JavaScript (and by extension TypeScript) has two bottom types : `null` and `undefined`. They are *intented* to mean different things:
3+
4+
* Something hasn't been initialized : `undefined`
5+
* Something is current unavailable: `null`
6+
7+
Most other languages only have one (commonly called `null`). Since by default JavaScript will evaluate an uninitialized variable / parameter / property to `undefined` (you don't get a choice) we recommend you just use that for your own *unavailable* status and don't bother with `null`.
8+
9+
## Real world discussions
10+
TypeScript team doesn't use `null` : [TypeScript coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines#null-and-undefined) and it hasn't caused any propblems. Douglas Crockford thinks [`null` is a bad idea](https://www.youtube.com/watch?v=PSGEjv3Tqo0&feature=youtu.be&t=9m21s) and we should all just use `undefined`
11+
12+
## Dealing with `null` style code bases
13+
If your code base interacts with other APIs that might give you a `null` you check with `== undefined` (instead of `===`). Using this is safe even for other potentially *falsy* values.
14+
```ts
15+
/// Image you are doing `foo == undefined` where foo can be one of:
16+
console.log(undefined == undefined); // true
17+
console.log(null == undefined); // true
18+
console.log(0 == undefined); // false
19+
console.log('' == undefined); // false
20+
console.log(false == undefined); // false
21+
```
22+
23+
## Additional tips
24+
25+
### Limit explict use of `undefined`
26+
Also because TypeScript gives you the opportunity to *document* your structures seperately from values instead of stuff like:
27+
```ts
28+
function foo(){
29+
// if Something
30+
return {a:1,b:2};
31+
// else
32+
return {a:1,b:undefined};
33+
}
34+
```
35+
you should use a type annotation:
36+
```ts
37+
function foo():{a:number,b?:number}{
38+
// if Something
39+
return {a:1,b:2};
40+
// else
41+
return {a:1};
42+
}
43+
```
44+
45+
### Node style callbacks
46+
Node style callback function (e.g. `(err,somethingElse)=>{ /* something */ }`) are generally called with `err` set to `null` if there isn't an error. You generally just use a truthy check for this anyways:
47+
48+
```ts
49+
fs.readFile('someFile', 'utf8', (err,data) => {
50+
if (err) {
51+
// do something
52+
}
53+
// no error
54+
});
55+
```
56+
When creating your own APIs its *okay* to use `null` in this case for consistency. In all sincerity for your own APIs you should look at promises, in that case you actually don't need to bother with absent error values (you handle them with `.then` vs. `.catch`).
57+
58+
### Don't use `undefined` as a means of denoting *validity*
59+
60+
For example an awful function like this:
61+
62+
```ts
63+
function toInt(str:string) {
64+
return str ? parseInt(str) : undefined;
65+
}
66+
```
67+
can be much better written like this:
68+
```ts
69+
function toInt(str: string): { valid: boolean, int?: number } {
70+
const int = parseInt(str);
71+
if (isNaN(int)) {
72+
return { valid: false };
73+
}
74+
else {
75+
return { valid: true, int };
76+
}
77+
}
78+
```

0 commit comments

Comments
 (0)