Skip to content

Commit 40e96de

Browse files
committed
Initial import from orta/typescript-notes
1 parent 340170e commit 40e96de

35 files changed

+2429
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,4 @@ dist
102102

103103
# TernJS port file
104104
.tern-port
105+
.DS_Store

GLOSSARY.md

+313
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
### Terminology from inside the codebase
2+
3+
- `Parser` - Takes source code and tries to convert it into an in-memory AST representation which you can work
4+
with in the compiler. Also: [see Parser](https://basarat.gitbooks.io/typescript/docs/compiler/parser.html)
5+
- `Scanner` - Used by the parser to convert a string an chops into tokens in a linear fashion, then it's up to a
6+
parser to tree-ify them. Also: [see Scanner](https://basarat.gitbooks.io/typescript/docs/compiler/scanner.html)
7+
- `Binder` - Creates a symbol map and uses the AST to provide the type system
8+
[See Binder](https://basarat.gitbooks.io/typescript/docs/compiler/binder.html)
9+
- `Checker` - Takes the AST, symbols and does the type checking and inference -
10+
[See Checker](https://basarat.gitbooks.io/typescript/docs/compiler/checker.html)
11+
- `Token` - A set of characters with some kind of semantic meaning, a parser generates a set of tokens
12+
- `AST` - An abstract syntax tree. Basically the in-memory representation of all the identifiers as a tree of
13+
tokens.
14+
- `Node` - An object that lives inside the tree
15+
- `Location` / `Range`
16+
- `Freshness` - When a literal type is first created and not expanded by hitting a mutable location, see [Widening
17+
and Narrowing in TypeScript][wnn].
18+
- `Symbol` - An object that tracks all the places a variable or type is declared
19+
- `Transient Symbol` - A symbol created in the checker, as opposed to in the binder
20+
21+
### Type stuff which can be see outside the compilers
22+
23+
- `Expando` - This is [the term](https://developer.mozilla.org/en-US/docs/Glossary/Expando) used to describe taking a JS object and adding new things to it which expands the type's shape
24+
25+
```js
26+
function doSomething() {}
27+
doSomething.doSomethingElse = () => {}
28+
```
29+
30+
In TS, this is only allowed for adding properties to functions. In JS, this is a normal pattern in old school code for all kinds of objects. TypeScript will augment the types for `doSomething` to add `doSomethingElse` in the type system in both.
31+
32+
33+
- `Structural Type System` - A school of types system where the way types are compared is via the structure of
34+
their properties.
35+
36+
For example:
37+
38+
```ts
39+
interface Duck {
40+
hasBeak: boolean;
41+
flap: () => void;
42+
}
43+
44+
interface Bird {
45+
hasBeak: boolean;
46+
flap: () => void;
47+
}
48+
```
49+
50+
These two are the exact same inside TypeScript. The basic rule for TypeScript’s structural type system is that
51+
`x` is compatible with `y` if `y` has at least the same members as `x`.
52+
53+
* `Literal` - A literal type is a type that only has a single value, e.g. `true`, `1`, `"abc"`, `undefined`.
54+
55+
For immutable objects, TypeScript creates a literal type which is the value. For mutable objects TypeScript
56+
uses the general type that the literal matches. See [#10676](https://github.com/Microsoft/TypeScript/pull/10676)
57+
for a longer explanation.
58+
59+
```ts
60+
// The types are the literal:
61+
const c1 = 1; // Type 1
62+
const c2 = c1; // Type 1
63+
const c3 = "abc"; // Type "abc"
64+
const c4 = true; // Type true
65+
const c5 = c4 ? 1 : "abc"; // Type 1 | "abc"
66+
67+
// The types are the class of the literal, because let allows it to change
68+
let v1 = 1; // Type number
69+
let v2 = c2; // Type number
70+
let v3 = c3; // Type string
71+
let v4 = c4; // Type boolean
72+
let v5 = c5; // Type number | string
73+
```
74+
75+
Literal types are sometimes called unit types, because they have only one ("unit") value.
76+
77+
- `Control Flow Analysis` - using the natural branching and execution path of code to change the types at
78+
different locations in your source code by static analysis.
79+
80+
```ts
81+
type Bird = { color: string, flaps: true };
82+
type Tiger = { color: string, stripes: true };
83+
declare animal: Bird | Tiger
84+
85+
if ("stripes" in animal) {
86+
// Inside here animal is only a tiger, because TS could figure out that
87+
// the only way you could get here is when animal is a tiger and not a bird
88+
}
89+
```
90+
91+
- `Generics` - A way to have variables inside a type system.
92+
93+
```ts
94+
function first(array: any[]): any {
95+
return array[0];
96+
}
97+
```
98+
99+
You want to be able to pass a variable type into this function, so you annotate the function with angle brackets
100+
and a _type parameter_:
101+
102+
```ts
103+
function first<T>(array: T[]): T {
104+
return array[0];
105+
}
106+
```
107+
108+
This means the return type of `first` is the same as the type of the array elements passed in. (These can start
109+
looking very complicated over time, but the principle is the same; it just looks more complicated because of the
110+
single letter.) Generic functions should always use their type parameters in more than one position (e.g. above,
111+
`T` is used both in the type of the `array` parameter and in the function’s return type). This is the heart of
112+
what makes generics useful—they can specify a _relationship_ between two types (e.g., a function’s output is the
113+
same as input, or a function’s two inputs are the same type). If a generic only uses its type parameter once, it
114+
doesn’t actually need to be generic at all, and indeed some linters will warn that it’s a _useless generic_.
115+
116+
Type parameters can usually be inferred from function arguments when calling generics:
117+
118+
```ts
119+
first([1, 2, 3]); // 'T' is inferred as 'number'
120+
```
121+
122+
It’s also possible to specify them explicitly, but it’s preferable to let inference work when possible:
123+
124+
```ts
125+
first<string>(["a", "b", "c"]);
126+
```
127+
128+
* `Outer type parameter` - A type parameter declared in a parent generic construct:
129+
130+
```ts
131+
class Parent<T> {
132+
method<U>(x: T, y: U): U {
133+
// 'T' is an *outer* type parameter of 'method'
134+
// 'U' is a *local* type parameter of 'method'
135+
}
136+
}
137+
```
138+
139+
* `Narrowing` - Taking a union of types and reducing it to fewer options.
140+
141+
A great case is when using `--strictNullCheck` when using control flow analysis
142+
143+
```ts
144+
// I have a dog here, or I don't
145+
declare const myDog: Dog | undefined;
146+
147+
// Outside the if, myDog = Dog | undefined
148+
if (dog) {
149+
// Inside the if, myDog = Dog
150+
// because the type union was narrowed via the if statement
151+
dog.bark();
152+
}
153+
```
154+
155+
- `Expanding` - The opposite of narrowing, taking a type and converting it to have more potential values.
156+
157+
```ts
158+
const helloWorld = "Hello World"; // Type; "Hello World"
159+
160+
let onboardingMessage = helloWorld; // Type: string
161+
```
162+
163+
When the `helloWorld` constant was re-used in a mutable variable `onboardingMessage` the type which was set is an
164+
expanded version of `"Hello World"` which went from one value ever, to any known string.
165+
166+
- `Transient` - a symbol created in the checker.
167+
168+
The checker creates its own symbols for unusual declarations:
169+
170+
1. Cross-file declarations
171+
172+
```ts
173+
// @filename: one.ts
174+
interface I { a }
175+
// @filename: two.ts
176+
interface I { b }
177+
```
178+
179+
The binder creates two symbols for I, one in each file. Then the checker creates a merged symbol that has both declarations.
180+
181+
2. Synthetic properties
182+
183+
```ts
184+
type Nats = Record<'one' | 'two', number>
185+
```
186+
187+
The binder doesn't create any symbols for `one` or `two`, because those properties don't exist until the Record mapped type creates them.
188+
189+
3. Complex JS patterns
190+
191+
```js
192+
var f = function g() {
193+
g.expando1 = {}
194+
195+
}
196+
f.expando2 = {}
197+
```
198+
199+
People can put expando properties on a function expression inside or outside the function, using different names.
200+
- `Partial Type` -
201+
- `Synthetic` - a property that doesn't have a declaration in source.
202+
- `Union Types`
203+
- `Enum`
204+
- `Discriminant`
205+
- `Intersection`
206+
- `Indexed Type` - A way to access subsets of your existing types.
207+
208+
```ts
209+
interface User {
210+
profile: {
211+
name: string;
212+
email: string;
213+
bio: string;
214+
};
215+
account: {
216+
id: string;
217+
signedUpForMailingList: boolean;
218+
};
219+
}
220+
221+
type UserProfile = User["profile"]; // { name: string, email: string, bio: string }
222+
type UserAccount = User["account"]; // { id: string, signedUpForMailingList: string }
223+
```
224+
225+
This makes it easier to keep a single source of truth in your types.
226+
227+
- `Index Signatures` - A way to tell TypeScript that you might not know the keys, but you know the type of values
228+
of an object.
229+
230+
```ts
231+
interface MySettings {
232+
[index: string]: boolean;
233+
}
234+
235+
declare function getSettings(): MySettings;
236+
const settings = getSettings();
237+
const shouldAutoRotate = settings.allowRotation; // boolean
238+
```
239+
240+
- `IndexedAccess` - ( https://github.com/Microsoft/TypeScript/pull/30769 )
241+
- `Conditional Types`
242+
- `Contextual Types`
243+
- `Substitution`
244+
- `NonPrimitive`
245+
- `Instantiable`
246+
- `Tuple` - A mathematical term for a finite ordered list. Like an array but with a known length.
247+
248+
TypeScript lets you use these as convenient containers with known types.
249+
250+
```ts
251+
// Any item has to say what it is, and whether it is done
252+
type TodoListItem = [string, boolean];
253+
254+
const chores: TodoListItem[] = [["read a book", true], ["done dishes", true], ["take the dog out", false]];
255+
```
256+
257+
Yes, you could use an object for each item in this example, but tuples are there when it fits your needs.
258+
259+
- `Mapped Type` - A type which works by taking an existing type and creating a new version with modifications.
260+
261+
```ts
262+
type Readonly<T> = { readonly [P in keyof T]: T[P] };
263+
264+
// Map for every key in T to be a readonly version of it
265+
// e.g.
266+
interface Dog {
267+
furColor: string;
268+
hasCollar: boolean;
269+
}
270+
271+
// Using this
272+
type ReadOnlyDog = Readonly<Dog>;
273+
274+
// Would be
275+
interface ReadonlyDog {
276+
readonly furColor: string;
277+
readonly hasCollar: boolean;
278+
}
279+
```
280+
281+
This can work where you
282+
283+
- `Type Assertion` - override its inferred and analyzed view of a type
284+
285+
```ts
286+
interface Foo {
287+
bar: number;
288+
bas: string;
289+
}
290+
var foo = {} as Foo;
291+
foo.bar = 123;
292+
foo.bas = "hello";
293+
```
294+
295+
- `Incremental Parsing` - Having an editor pass a range of edits, and using that range to invalidate a cache of
296+
the AST. Re-running the type checker will keep the out of range nodes and only parse the new section.
297+
- `Incremental Compiling` - The compiler keeps track of all compilation hashes, and timestamps when a file has
298+
been transpiled. Then when a new module is changed, it will use the import/export dependency graph to invalidate
299+
and re-compile only the affected code.
300+
301+
### Rarely heard
302+
303+
- `Deferred`
304+
- `Homomorphic`
305+
306+
### JS Internals Specifics
307+
308+
[`Statement`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements) - "JavaScript
309+
applications consist of statements with an appropriate syntax. A single statement may span multiple lines.
310+
Multiple statements may occur on a single line if each statement is separated by a semicolon. This isn't a
311+
keyword, but a group of keywords."
312+
313+
[wnn]: https://github.com/sandersn/manual/blob/master/Widening-and-Narrowing-in-Typescript.md

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
# TypeScript Compiler Notes
2+
3+
This repo is a corpus of notes from many engineers over time on different systems inside the TypeScript codebase. It is not meant as a "one true" source of authoritative documentation for the TypeScript compiler API, but as a way to ease contributions to the [`microsoft/TypeScript`](https://github.com/microsoft/TypeScript) repo.
4+
5+
## Get Started
6+
7+
If you are completely new to the TypeScript codebase, this YouTube video covers all of the major systems involved in converting files to JavaScript, and type-checking types which will provide a high level guide to what you may be interested in focusing on:
8+
9+
<a href='https://www.youtube.com/watch?v=X8k_4tZ16qU&list=PLYUbsZda9oHu-EiIdekbAzNO0-pUM5Iqj&index=4'><img src="https://user-images.githubusercontent.com/49038/140491214-720ce354-e526-4599-94ec-72cdbecc2b01.png" /></a>
10+
11+
From there, you can start in the [First Steps to Contributing to the TypeScript Repo](./first_steps.md) consult the [Glossary](./GLOSSARY.md) or dive directly into the [`./codebase/`](./codebase) or [`./systems/`](./systems) folders.
12+
13+
## Compilers in General
14+
15+
- Learn how TypeScript works by reading the [mini-TypeScript implementation](https://github.com/sandersn/mini-typescript#mini-typescript)
16+
- Recommended link for learning how compilers work: https://c9x.me/compile/bib/
117

218
# Contributing
319

2.79 KB
Loading
136 KB
Loading

0 commit comments

Comments
 (0)