Skip to content

Commit 974ce61

Browse files
authored
feat: ✨ getting started JS/TS (#41)
* feat: ✨ getting started JS/TS * chore: 🔧 address nits
1 parent 479d008 commit 974ce61

File tree

8 files changed

+286
-9
lines changed

8 files changed

+286
-9
lines changed

content/docs/contributor/common/code-quality/index.mdx renamed to content/docs/contributor/common/code-quality.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ title: Code Quality
33
description: Working toward consistently high code quality and its unique importance within ICSSC.
44
---
55

6+
import {Callout} from "fumadocs-ui/components/callout";
7+
68
Good code quality and practices are generally regarded as important for most projects. However, due to the nature of our organization, it is especially critical.
79

810
## Importance
@@ -44,4 +46,4 @@ Code review is a critical part of our development process. This is where design
4446

4547
### 3. Continuous Automation
4648

47-
As with the path of least resistance, it's also critical to identify new pain points and implement solutions on top of our [common toolchain](/docs/contributor/common/code-quality/toolchain). Most importantly, new automations allow us to make lasting improvements, mitigating against our high turnover rate (due to members graduating and leaving).
49+
As with the path of least resistance, it's also critical to identify new pain points and implement solutions on top of our [common toolchain](/docs/contributor/common/toolchain). Most importantly, new automations allow us to make lasting improvements, mitigating against our high turnover rate (due to members graduating and leaving).

content/docs/contributor/common/code-quality/meta.json

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: Introduction
3+
---
4+
5+
Thank you for your interest in contributing to ICSSC's projects! We're happy to have you here; after all, open source is a large part of what enables our projects to continue improving.
6+
7+
This article will get you on the path to making an open source contribution to one of our projects. We recognize that you all come from a diversity of backgrounds, and that what works for some of you may not work for others. As such, we will introduce only topics that are directly relevant to your work with ICSSC's projects.
8+
9+
We assume that you have a working knowledge of the following topics:
10+
* A general-purpose programming language (_e.g._, Python, C++, Java)
11+
* HTML and CSS
12+
* Git and GitHub
13+
14+
If you're unsure as to your proficiency in these topics, don't fret! The Internet has many wonderful resources on these subjects, far better and more comprehensive than anything we can pack in a simple documentation page, which is why we chose not to introduce such topics. You can always consult these resources and then come back; we'll still be here.
15+
16+
But if you're ready, read on!
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
---
2+
title: JavaScript and TypeScript
3+
---
4+
5+
import Link from "next/link";
6+
import {Callout} from "fumadocs-ui/components/callout";
7+
8+
*JavaScript* is a high-level programming language used in many places, but particularly in web development as "the language of the Web." *TypeScript* builds on top of JavaScript by providing a *type system*, ensuring that certain kinds of errors never make it to runtime.
9+
10+
The overwhelming majority of projects developed and maintained by ICSSC Projects use TypeScript as their primary language. This is to ensure that anyone who is interested in contributing to one project may, with minimal effort, also contribute to another project.
11+
12+
Below, we'll provide a quick overview of the basics of JavaScript, including some patterns that we use frequently in our codebases. We'll then introduce TypeScript's type system and how it's enforced.
13+
14+
<Callout>
15+
In this and future parts of the Getting Started guide, we will introduce new terms in *italics*.
16+
17+
Any points that are particularly important, which we really want you to take away from this guide, will be in **bold**.
18+
19+
Supplementary notes, like this one, will be enclosed in a box like this called a *Callout*.
20+
</Callout>
21+
22+
## Introduction to JavaScript
23+
24+
### Printing
25+
26+
As a product of the Web, the primary way that JavaScript interacts with standard input and output is through an object called `console`, which as its name suggests is an interface to your browser's developer console. `console` is used even in server-side code, except that it writes to the terminal instead.
27+
28+
```js
29+
console.log("Hello, world!");
30+
```
31+
32+
### Variables
33+
34+
Unlike some other languages, you can declare constants in JavaScript using the keyword `const`, and JavaScript will make sure that it cannot be modified. It's recommended that you use `const` as much as possible, and only use the keyword `let` for things that absolutely must change at some point (for instance, loop counters).
35+
36+
In some older code you may also see the keyword `var`. The use of `var` is not considered best practice anymore, so you should avoid using it. `let` does the same thing in 99% of cases.
37+
38+
```js
39+
let s = "foo";
40+
s = "bar"; // this is OK
41+
42+
const pi = 3.14;
43+
pi = 6.28; // this causes an error
44+
```
45+
46+
### Strings and string interpolation
47+
48+
Strings function much the same in JavaScript as in any other programming language, but one feature that JavaScript has that some others may not is *string interpolation*. This allows you to put any expression or value into a string, while enhancing readability because the value or expression is located where it will appear in the string, rather than after.
49+
50+
```js
51+
const likes = 5;
52+
console.log(`This post has ${likes} likes.`); // This post has 5 likes.
53+
console.log(`I wish I had ${likes * 10} likes!`); // I wish I had 50 likes!
54+
```
55+
56+
### Equality
57+
58+
JavaScript has two types of equality operators, `==` and `===` (and their negations, `!=` and `!==`). Due to historical reasons, `==` and `!=` exhibit distinctively non-intuitive behavior. For example:
59+
60+
```js
61+
console.log("" == false) // true - but why?????
62+
console.log("" === false) // false - obviously
63+
```
64+
65+
For this reason, you should almost always use `===` and `!==`.
66+
67+
### Functions: arrows, anonymity, oh my!
68+
69+
While we're on the subject of JavaScript having many ways to do almost (but not quite) the same thing, there are many ways to declare a function, each with their own quirks. We won't be going into too much detail here, and will only make our recommendations on which ones to use (and which are commonly used in our projects' codebases).
70+
71+
You can declare a function the classic way, using the `function` keyword:
72+
```js
73+
function sayHello() {
74+
console.log("Hello, world!");
75+
}
76+
```
77+
78+
But you can also declare an *anonymous function* and assign it to a variable:
79+
```js
80+
const sayHello = function () {
81+
console.log("Hello, world!");
82+
}
83+
```
84+
Needless to say, this pattern is verbose for no real good reason, and should almost never be used.
85+
86+
A pattern that looks like this, but is more concise and thus very commonly used, is the *arrow function*:
87+
```js
88+
const sayHello = () => {
89+
console.log("Hello, world!")
90+
}
91+
```
92+
93+
If your arrow function returns the value of a single expression, it can be made even more concise by eliminating the curly braces, like so:
94+
```js
95+
const cylinderVolume = (r, h) => Math.PI * (r ** 2) * h;
96+
```
97+
98+
Functions are an extremely powerful part of JavaScript: they can be passed as arguments to other functions, which can enable you to write extremely clean and easily maintainable code. You'll see more examples of code written in this fashion, known as *functional programming*, below.
99+
100+
### Arrays and comparators
101+
102+
One major quirk (and one that causes beginners hours of pain) of JavaScript arrays is that by default, its `.sort()` method sorts the array in alphabetical order as if the elements were strings, even if they are not. This quirk is easily illustrated like so:
103+
```js
104+
const numbers = [3, 2, 11, 1, 4];
105+
// you might expect 11 to be last...
106+
numbers.sort()
107+
// ...but it's not:
108+
console.log(numbers) // [1, 11, 2, 3, 4] - boo
109+
```
110+
111+
We can override this default (and frankly nonsensical) behavior by providing our own *comparator function*. This function just takes in two elements, and depending on their values in relation to each other, returns another value.
112+
| `compareFunction(a, b)` return value | Resulting sort order |
113+
|--------------------------------------|------------------------------------|
114+
| a positive number | sort `b` before `a` |
115+
| a negative number | sort `a` before `b` |
116+
| zero | if `a` was first, keep it that way |
117+
118+
In our instance, we can have our array be sorted properly by using a simple arrow function that just subtracts `b` from `a`, so the ordering is correct:
119+
```js
120+
const numbers = [3, 2, 11, 1, 4];
121+
numbers.sort((a, b) => a - b);
122+
console.log(numbers) // [1, 2, 3, 4, 11] - yay!
123+
```
124+
125+
### Array methods
126+
JavaScript arrays also come with a multitude of methods that can be used to do things with the array's contents. The most commonly used method is `.map()`:
127+
```js
128+
const numbers = [1, 2, 3, 4];
129+
const double = (x) => x * 2;
130+
const doubled = numbers.map(double);
131+
console.log(doubled) // [2, 4, 6, 8]
132+
```
133+
134+
That's cool and all, but let's look at a problem that's a bit more complicated. Suppose you have an array of numbers, and you want to write a function that returns the sum of all the even numbers in the array. You could probably accomplish this task with loops, like so:
135+
```js
136+
const numbers = [1, 2, 3, 4];
137+
function sumOfEvens(nums) {
138+
let sum = 0;
139+
for (let i = 0; i < nums.length; ++i) {
140+
if (nums[i] % 2 === 0) {
141+
sum += nums[i];
142+
}
143+
}
144+
return sum;
145+
}
146+
console.log(sumOfEvens(numbers)); // 6
147+
```
148+
149+
But what if I told you this could be a one-line arrow function?
150+
```js
151+
const numbers = [1, 2, 3, 4];
152+
const sumOfEvens = (nums) => nums.filter((num) => num % 2 === 0).reduce((acc, i) => acc + i, 0);
153+
console.log(sumOfEvens(numbers)); // 6
154+
```
155+
Don't just take my word for it - paste this into your browser console or Node.js window, and see if it's true. This is the power of JavaScript's array methods, and more broadly, functional programming. For this reason, array method chaining is used quite a bit throughout our codebases.
156+
157+
However, it's important to recall that **functional programming is not a cure-all**: there are some places where loops may be more readable and make more sense than chaining array methods, and that's fine!
158+
159+
### Objects
160+
Objects in JavaScript are commonly used in a similar way to dictionaries or hash maps in other languages. Unlike some other languages, however, you don't need quotes around the keys. Also, you can access the values using either bracket or dot notation. This makes objects in JavaScript function similar to data classes or data transfer objects in other languages.
161+
```js
162+
const ages = { alice: 40, bob: 35, carol: 13 };
163+
console.log(ages["alice"]); // 40
164+
console.log(ages.bob); // 35
165+
```
166+
167+
If you have a constant you'd like to turn into a key of an object, you can do that too by surrounding it with square brackets, like so:
168+
```js
169+
const name = "dan";
170+
const ages = { [name]: 55 };
171+
console.log(ages.dan); // 55
172+
```
173+
174+
## Introduction to TypeScript
175+
176+
Now that you're more familiar with JavaScript, let's bring on some additional complexity with TypeScript.
177+
178+
### Built-in types
179+
180+
TypeScript understands that JavaScript has a few built-in types, even if it doesn't have type checking. Its built-in type system is thus built upon these types:
181+
182+
Let's look at a few examples:
183+
* `boolean` and `string` are as you would expect in any other language.
184+
* `number` represents any number, integer or floating-point - JavaScript doesn't make a distinction, so neither does TypeScript.
185+
* `undefined` and `null` are special types that represent a value which doesn't exist. `undefined` is the default value of any variable that hasn't been initialized while `null` must be assigned deliberately. However, a variable of type `undefined` cannot have the value `null`, and vice versa.
186+
* `void` is the return type of a function that doesn't return anything.
187+
* `never` is the return type of a function that never returns, i.e. always throws an error or terminates the program.
188+
* `unknown` is used to denote data whose type and structure are not known.
189+
* `any` is similar to `unknown`, but overrides type checking entirely for that object. As it defeats the purpose of TypeScript, it should be used sparingly.
190+
191+
### Assigning types
192+
193+
Generally, TypeScript is smart enough to figure out the types of new variables based on what value they have. Therefore, unless the *inferred type* is wrong, you don't really need to declare the type explicitly.
194+
195+
However, if you use a `let` declared variable with no initial value, TypeScript will likely require you to explicitly declare the type.
196+
197+
Function parameters should almost always have types, since that's how you can provide information to whoever is using your function on what types the arguments of your function takes.
198+
199+
```ts
200+
const aNumber: number = 42;
201+
const anotherNumber = 100; // the type of `anotherNumber` is automatically inferred as `number`
202+
203+
let x; // no type inference going on here
204+
x = 2;
205+
206+
function addNumbers(
207+
a: number,
208+
b: number // parameters should have types...
209+
) { // but return types don't necessarily need to be explicitly declared
210+
return a + b;
211+
}
212+
```
213+
214+
### Object types
215+
216+
Aside from built-in types, TypeScript also supports typing the values of objects. This is immensely powerful; with it, you can model data in a type-safe manner, ensuring that you don't accidentally access a property that doesn't exist, or write data of an incompatible type to a field.
217+
218+
There are two main ways to declare object types, *type aliases* and *interfaces*:
219+
```ts
220+
type User = {
221+
name: string;
222+
id: number;
223+
}
224+
```
225+
```ts
226+
interface User {
227+
name: string;
228+
id: number;
229+
}
230+
```
231+
232+
While they look similar, type aliases and interfaces have some subtle syntactic differences. Each ICSSC project may have its own convention on when to use type aliases or interfaces (and when not to), so it's important to follow the project's conventions.
233+
234+
### Unions
235+
236+
Unions allow us to create a type that can be any one of a list of types which we provide. The most straightforward application of this is
237+
in creating something akin to enums in other languages:
238+
```ts
239+
type PrimaryColors = "Red" | "Yellow" | "Blue";
240+
```
241+
<Callout>
242+
You may or may not have noticed that `enum`s do exist in TypeScript! However, like with `var`, their use is not recommended.
243+
</Callout>
244+
245+
Another pattern that is commonly seen in some of our projects is the *tagged union*. The tagged union is commonly implemented as a union of several objects that are otherwise different, but which share one property. It is extremely powerful because it's extremely easy to discern which object you're dealing with just by checking the shared property.
246+
```ts
247+
type SuccessResponse = { success: true, message: string };
248+
type FailureResponse = { success: false, error: string };
249+
type ResponseObject = SuccessResponse | FailureResponse;
250+
251+
function processResponse(res: ResponseObject) {
252+
if (res.success) {
253+
console.log(`Success! Message was: ${res.message}`);
254+
} else {
255+
console.log(`Failure! Error was: ${res.error}`);
256+
}
257+
}
258+
```
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"title": "Getting Started",
3+
"pages": ["introduction", "javascript-and-typescript"]
4+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"title": "Common",
3-
"pages": ["code-quality"]
3+
"pages": ["getting-started", "code-quality", "toolchain"]
44
}
File renamed without changes.

content/docs/contributor/index.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
---
22
title: Contributor
3-
description: Documentation for internal members, or contributors interested in working on ICSSC projects.
3+
description: Documentation for internal members, or contributors interested in working on ICSSC's projects.
44
---
55

6-
{/* the word projects is intentionally lowercase. referring to projects, rather than the committee ICSSC Project. */}
6+
This section is intended for internal members, or open source contributors interested in working on ICSSC's projects. It will cover organizational principles, local setup, and design decisions.
77

8-
This section is intended for internal members, or open source contributors interested in working on ICSSC projects. It will cover organizational principles, local setup, and design decisions.
8+
Want to get started? Look no further than [here](/docs/contributor/common/getting-started/introduction).
99

1010
## Projects
1111

1212
import AntAlmanac from "@/components/logos/AntAlmanac";
1313
import PeterPortal from "@/components/logos/PeterPortal";
1414
import Zotistics from "@/components/logos/Zotistics";
15+
import {Card, Cards} from "fumadocs-ui/components/card";
1516
import { Workflow, UtensilsCrossed, Bird, CalendarRange } from "lucide-react";
1617

1718
<Cards>

0 commit comments

Comments
 (0)