Skip to content

Commit 35eeb8c

Browse files
Add Concept Exercise for type checking. (#2704)
--------- Co-authored-by: Derk-Jan Karrenbeld <[email protected]>
1 parent 7367d5d commit 35eeb8c

File tree

20 files changed

+1393
-0
lines changed

20 files changed

+1393
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"blurb": "Learn how to check the type of a value or object in JavaScript",
3+
"authors": [
4+
"quintuple-mallard",
5+
"SleeplessByte"
6+
],
7+
"contributors": []
8+
}

concepts/type-checking/about.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# About
2+
3+
Knowning what the type of a piece of data is, is often very important for code to run smoothly and without errors.
4+
5+
Javascript has several ways to check the type of a value or object.
6+
7+
```exercism/note
8+
Javascript's type checking mechanisms can be somewhat unreliable.
9+
10+
For better type safety and stronger types, you should probably use TypeScript, a language that builds on JavaScript, but with the type syntax of a static-typed language.
11+
```
12+
13+
## The `typeof` operator
14+
15+
The `typeof` operator returns the type of its operand.
16+
The output is a string matching the name of one of the [primitive data types][primitives], except for `"null"`.
17+
It can also be `"function"` or `"object"`.
18+
19+
```javascript
20+
typeof undefined;
21+
// => "undefined"
22+
23+
typeof true;
24+
// => "boolean"
25+
26+
typeof 42;
27+
// => "number"
28+
29+
typeof 'Hello, World!';
30+
// => "string"
31+
32+
typeof function () {
33+
return 'Hello, World';
34+
};
35+
// => "function"
36+
37+
typeof [1, 2, 3, 4];
38+
// => "object"
39+
40+
typeof { city: 'Stockholm', country: 'Sweden' };
41+
// => "object"
42+
```
43+
44+
For [historical reasons][`typeof null` is `"object"`].
45+
46+
## The `instanceof` operator
47+
48+
For checking the type of an object, you can use the `instanceof` operator.
49+
It evaluates into a `boolean` depending on whether the second operand is included in the first operands' [prototype chain][prototype chain].
50+
To clarify, `instanceof` will return whether the first operand is an instance of second operand or one of its child classes.
51+
`instanceof` only works on objects.
52+
53+
```javascript
54+
class Beverage {
55+
// ...
56+
}
57+
58+
// The Coffee class is a child of the Beverage class.
59+
class Coffee extends Beverage {
60+
// ...
61+
}
62+
63+
const java = new Coffee();
64+
65+
java instanceof Coffee;
66+
// => true
67+
68+
java instanceof Beverage;
69+
// => true
70+
```
71+
72+
````exercism/advanced
73+
The `Array` class has a method called `Array.isArray()` that checks if its argument is an array.
74+
75+
While `instanceof Array` will not work with an array created in a different realm such as an `iframe` in a webpage, `Array.isArray()` will.
76+
77+
This is because the Array class has a different constructor in each realm, and each `iframe` has its own ream, meaning that the function in the prototype chain will be different, causing `instanceof Array` to fail.
78+
`Array.isArray()` is capable of ignoring this, and should always be used when possible.
79+
80+
It can also survive false positives where an object isn't actually an `Array`, and merely has `Array` in its prototype chain.
81+
82+
```javascript
83+
({ __proto__: Array.prototype }) instanceof Array
84+
// => true
85+
86+
Array.isArray({ __proto__: Array.prototype })
87+
// => false
88+
```
89+
90+
````
91+
92+
## The `in` operator
93+
94+
The `in` operator returns whether the first operand is a property of the second operand.
95+
It does not check that the property has a defined value.
96+
A property set to `undefined` will still be detected by `in`.
97+
98+
```javascript
99+
class Coffee {
100+
constructor() {
101+
this.temperature = 'hot';
102+
this.isDarkMatter = undefined;
103+
}
104+
105+
coolDown() {
106+
this.temperature = 'warm';
107+
}
108+
}
109+
110+
const espresso = new Coffee();
111+
112+
'temperature' in espresso;
113+
// => true
114+
115+
'color' in espresso;
116+
// => false
117+
118+
'isDarkMatter' in espresso;
119+
// => true
120+
```
121+
122+
````exercism/note
123+
`in` will return `true` for inherited properties and methods.
124+
125+
```javascript
126+
"coolDown" in espresso
127+
// => true
128+
129+
"constructor" in espresso
130+
// => true
131+
```
132+
133+
To avoid this, use `Object.hasOwn()` instead
134+
````
135+
136+
## The `Object.hasOwn()` function
137+
138+
The `Object.hasOwn()` method returns whether the specified object _owns the given property_ (it is not inherited or a method).
139+
140+
```javascript
141+
class Coffee {
142+
constructor() {
143+
this.temperature = 'hot';
144+
}
145+
146+
coolDown() {
147+
this.temperature = 'warm';
148+
}
149+
}
150+
const cappuccino = new Coffee();
151+
152+
Object.hasOwn(cappucino, 'temperature');
153+
// => true
154+
155+
Object.hasOwn(cappucino, 'constructor');
156+
// => false
157+
158+
Object.hasOwn(cappucino, 'coolDown');
159+
// => false
160+
```
161+
162+
[primitives]: https://developer.mozilla.org/en-US/docs/Glossary/Primitive
163+
[typeof null is object]: https://2ality.com/2013/10/typeof-null.html
164+
[prototype chain]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# About
2+
3+
Knowning what the type of a piece of data is, is often very important for code to run smoothly and without errors.
4+
5+
Javascript has several ways to check the type of a value or object.
6+
7+
```exercism/note
8+
Javascript's type checking mechanisms can be somewhat unreliable.
9+
10+
For better type safety and stronger types, you should probably use TypeScript, a language that builds on JavaScript, but with the type syntax of a static-typed language.
11+
```
12+
13+
## The `typeof` operator
14+
15+
The `typeof` operator returns the type of its operand.
16+
The output is a string matching the name of one of the [primitive data types][primitives], except for `"null"`.
17+
It can also be `"function"` or `"object"`.
18+
19+
```javascript
20+
typeof undefined;
21+
// => "undefined"
22+
23+
typeof true;
24+
// => "boolean"
25+
26+
typeof 42;
27+
// => "number"
28+
29+
typeof 'Hello, World!';
30+
// => "string"
31+
32+
typeof function () {
33+
return 'Hello, World';
34+
};
35+
// => "function"
36+
37+
typeof [1, 2, 3, 4];
38+
// => "object"
39+
40+
typeof { city: 'Stockholm', country: 'Sweden' };
41+
// => "object"
42+
```
43+
44+
For [historical reasons][`typeof null` is `"object"`].
45+
46+
## The `instanceof` operator
47+
48+
For checking the type of an object, you can use the `instanceof` operator.
49+
It evaluates into a `boolean` depending on whether the second operand is included in the first operands' [prototype chain][prototype chain].
50+
To clarify, `instanceof` will return whether the first operand is an instance of second operand or one of its child classes.
51+
`instanceof` only works on objects.
52+
53+
```javascript
54+
class Beverage {
55+
// ...
56+
}
57+
58+
// The Coffee class is a child of the Beverage class.
59+
class Coffee extends Beverage {
60+
// ...
61+
}
62+
63+
const java = new Coffee();
64+
65+
java instanceof Coffee;
66+
// => true
67+
68+
java instanceof Beverage;
69+
// => true
70+
```
71+
72+
````exercism/advanced
73+
The `Array` class has a method called `Array.isArray()` that checks if its argument is an array.
74+
75+
While `instanceof Array` will not work with an array created in a different realm such as an `iframe` in a webpage, `Array.isArray()` will.
76+
77+
This is because the Array class has a different constructor in each realm, and each `iframe` has its own ream, meaning that the function in the prototype chain will be different, causing `instanceof Array` to fail.
78+
`Array.isArray()` is capable of ignoring this, and should always be used when possible.
79+
80+
It can also survive false positives where an object isn't actually an `Array`, and merely has `Array` in its prototype chain.
81+
82+
```javascript
83+
({ __proto__: Array.prototype }) instanceof Array
84+
// => true
85+
86+
Array.isArray({ __proto__: Array.prototype })
87+
// => false
88+
```
89+
90+
````
91+
92+
## The `in` operator
93+
94+
The `in` operator returns whether the first operand is a property of the second operand.
95+
It does not check that the property has a defined value.
96+
A property set to `undefined` will still be detected by `in`.
97+
98+
```javascript
99+
class Coffee {
100+
constructor() {
101+
this.temperature = 'hot';
102+
this.isDarkMatter = undefined;
103+
}
104+
105+
coolDown() {
106+
this.temperature = 'warm';
107+
}
108+
}
109+
110+
const espresso = new Coffee();
111+
112+
'temperature' in espresso;
113+
// => true
114+
115+
'color' in espresso;
116+
// => false
117+
118+
'isDarkMatter' in espresso;
119+
// => true
120+
```
121+
122+
````exercism/note
123+
`in` will return `true` for inherited properties and methods.
124+
125+
```javascript
126+
"coolDown" in espresso
127+
// => true
128+
129+
"constructor" in espresso
130+
// => true
131+
```
132+
133+
To avoid this, use `Object.hasOwn()` instead
134+
````
135+
136+
## The `Object.hasOwn()` function
137+
138+
The `Object.hasOwn()` method returns whether the specified object _owns the given property_ (it is not inherited or a method).
139+
140+
```javascript
141+
class Coffee {
142+
constructor() {
143+
this.temperature = 'hot';
144+
}
145+
146+
coolDown() {
147+
this.temperature = 'warm';
148+
}
149+
}
150+
const cappuccino = new Coffee();
151+
152+
Object.hasOwn(cappucino, 'temperature');
153+
// => true
154+
155+
Object.hasOwn(cappucino, 'constructor');
156+
// => false
157+
158+
Object.hasOwn(cappucino, 'coolDown');
159+
// => false
160+
```
161+
162+
[primitives]: https://developer.mozilla.org/en-US/docs/Glossary/Primitive
163+
[typeof null is object]: https://2ality.com/2013/10/typeof-null.html
164+
[prototype chain]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain

concepts/type-checking/links.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof",
4+
"description": "MDN: The typeof operator"
5+
},
6+
{
7+
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof",
8+
"description": "MDN: The instanceof operator"
9+
},
10+
{
11+
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty",
12+
"description": "MDN: The object.hasOwnProperty() method"
13+
}
14+
]

config.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,22 @@
436436
"objects",
437437
"functions"
438438
]
439+
},
440+
{
441+
"slug": "recycling-robot",
442+
"name": "Recycling Robot",
443+
"uuid": "16114449-52fe-470e-af11-cf9dc3689a93",
444+
"concepts": [
445+
"type-checking"
446+
],
447+
"prerequisites": [
448+
"basics",
449+
"errors",
450+
"objects",
451+
"arrays",
452+
"classes",
453+
"inheritance"
454+
]
439455
}
440456
],
441457
"practice": [
@@ -2887,6 +2903,11 @@
28872903
"uuid": "ca322d6f-0f7e-4a2d-a058-e98a59cdae93",
28882904
"slug": "randomness",
28892905
"name": "Randomness"
2906+
},
2907+
{
2908+
"uuid": "72e51fbe-db98-492e-b155-8ef21623f741",
2909+
"slug": "type-checking",
2910+
"name": "Type Checking"
28902911
}
28912912
],
28922913
"key_features": [

0 commit comments

Comments
 (0)