mirror of
https://github.com/gibbok/typescript-book
synced 2024-11-16 19:47:27 +01:00
MOD: typo and bullet format (#23)
- Fix typo - Fix bullet format - Remove extra white spaces
This commit is contained in:
parent
b0dca40d04
commit
76d2e0e93d
1 changed files with 9 additions and 61 deletions
70
README.md
70
README.md
|
@ -267,7 +267,6 @@ For instance, consider a function in a JavaScript file with the `.js` extension,
|
|||
<!-- skip -->
|
||||
```typescript
|
||||
const sum = (a, b) => a + b;
|
||||
|
||||
```
|
||||
|
||||
The function can be converted and used in TypeScript by changing the file extension to `.ts`. However, if the same function is annotated with TypeScript types, it cannot be executed in any JavaScript engine without compilation. The following TypeScript code will produce a syntax error if it is not compiled:
|
||||
|
@ -275,7 +274,6 @@ The function can be converted and used in TypeScript by changing the file extens
|
|||
<!-- skip -->
|
||||
```typescript
|
||||
const sum = (a: number, b: number): number => a + b;
|
||||
|
||||
```
|
||||
|
||||
TypeScript was designed to detect possible exceptions that can occur at runtime during compilation time by having the developer define the intent with type annotations. In addition, TypeScript can also catch issues if no type annotation is provided. For instance, the following code snippet does not specify any TypeScript types:
|
||||
|
@ -284,7 +282,6 @@ TypeScript was designed to detect possible exceptions that can occur at runtime
|
|||
```typescript
|
||||
const items = [{ x: 1 }, { x: 2 }];
|
||||
const result = items.filter(item => item.y);
|
||||
|
||||
```
|
||||
|
||||
In this case, TypeScript detects an error and reports:
|
||||
|
@ -295,7 +292,6 @@ TypeScript's type system is largely influenced by the runtime behavior of JavaSc
|
|||
|
||||
```typescript
|
||||
const result = '1' + 1; // Result is of type string
|
||||
|
||||
```
|
||||
|
||||
The team behind TypeScript has made a deliberate decision to flag unusual usage of JavaScript as errors. For instance, consider the following valid JavaScript code:
|
||||
|
@ -303,7 +299,6 @@ The team behind TypeScript has made a deliberate decision to flag unusual usage
|
|||
<!-- skip -->
|
||||
```typescript
|
||||
const result = 1 + true; // In JavaScript, the result is equal 2
|
||||
|
||||
```
|
||||
|
||||
However, TypeScript throws an error:
|
||||
|
@ -321,7 +316,6 @@ Here is an example of TypeScript code with a type error:
|
|||
```typescript
|
||||
const add = (a: number, b: number): number => a + b;
|
||||
const result = add('x', 'y'); // Argument of type 'string' is not assignable to parameter of type 'number'.
|
||||
|
||||
```
|
||||
|
||||
However, it can still produce executable JavaScript output:
|
||||
|
@ -331,7 +325,6 @@ However, it can still produce executable JavaScript output:
|
|||
'use strict';
|
||||
const add = (a, b) => a + b;
|
||||
const result = add('x', 'y'); // xy
|
||||
|
||||
```
|
||||
|
||||
It is not possible to check TypeScript types at runtime. For example:
|
||||
|
@ -353,7 +346,6 @@ const makeNoise = (animal: Animal) => {
|
|||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
As the types are erased after compilation, there is no way to run this code in JavaScript. To recognize types at runtime, we need to use another mechanism. TypeScript provides several options, with a common one being "tagged union". For example:
|
||||
|
@ -382,7 +374,6 @@ const dog: Dog = {
|
|||
bark: () => console.log('bark'),
|
||||
};
|
||||
makeNoise(dog);
|
||||
|
||||
```
|
||||
|
||||
The property "kind" is a value that can be used at runtime to distinguish between objects in JavaScript.
|
||||
|
@ -417,7 +408,6 @@ const makeNoise = (mammal: Mammal) => {
|
|||
|
||||
const dog = new Dog('Fido', () => console.log('bark'));
|
||||
makeNoise(dog);
|
||||
|
||||
```
|
||||
|
||||
In JavaScript, a "class" has a "prototype" property, and the "instanceof" operator can be used to test if the prototype property of a constructor appears anywhere in the prototype chain of an object.
|
||||
|
@ -638,7 +628,6 @@ type Y = {
|
|||
};
|
||||
const x: X = { a: 'a' };
|
||||
const y: Y = x; // Valid
|
||||
|
||||
```
|
||||
|
||||
### TypeScript Fundamental Comparison Rules
|
||||
|
@ -653,7 +642,6 @@ type X = {
|
|||
};
|
||||
const y = { a: 'A', b: 'B' }; // Valid, as it has at least the same members as X
|
||||
const r: X = y;
|
||||
|
||||
```
|
||||
|
||||
Function parameters are compared by types, not by their names:
|
||||
|
@ -665,7 +653,6 @@ let x: X = (j: number) => undefined;
|
|||
let y: Y = (k: number) => undefined;
|
||||
y = x; // Valid
|
||||
x = y; // Valid
|
||||
|
||||
```
|
||||
|
||||
Function return types must be the same:
|
||||
|
@ -678,7 +665,6 @@ let x: X = (a: number) => undefined;
|
|||
let y: Y = (a: number) => 1;
|
||||
y = x; // Invalid
|
||||
x = y; // Invalid
|
||||
|
||||
```
|
||||
|
||||
The return type of a source function must be a subtype of the return type of a target function:
|
||||
|
@ -689,14 +675,12 @@ let x = () => ({ a: 'A' });
|
|||
let y = () => ({ a: 'A', b: 'B' });
|
||||
x = y; // Valid
|
||||
y = x; // Invalid member b is missing
|
||||
|
||||
```
|
||||
|
||||
Discarding function parameters is allowed, as it is a common practice in JavaScript, for instance using Array.prototype.map():
|
||||
|
||||
```typescript
|
||||
[1, 2, 3].map((element, _index, _array) => element + 'x');
|
||||
|
||||
```
|
||||
|
||||
Therefore, the following type declarations are completely valid:
|
||||
|
@ -707,7 +691,6 @@ type Y = (a: number, b: number) => undefined;
|
|||
let x: X = (a: number) => undefined;
|
||||
let y: Y = (a: number) => undefined; // Missing b parameter
|
||||
y = x; // Valid
|
||||
|
||||
```
|
||||
|
||||
Any additional optional parameters of the source type are valid:
|
||||
|
@ -719,7 +702,6 @@ let x: X = a => undefined;
|
|||
let y: Y = a => undefined;
|
||||
y = x; // Valid
|
||||
x = y; //Valid
|
||||
|
||||
```
|
||||
|
||||
Any optional parameters of the target type without corresponding parameters in the source type are valid and not an error:
|
||||
|
@ -731,7 +713,6 @@ let x: X = a => undefined;
|
|||
let y: Y = a => undefined;
|
||||
y = x; // Valid
|
||||
x = y; // Valid
|
||||
|
||||
```
|
||||
|
||||
The rest parameter is treated as an infinite series of optional parameters:
|
||||
|
@ -739,7 +720,6 @@ The rest parameter is treated as an infinite series of optional parameters:
|
|||
```typescript
|
||||
type X = (a: number, ...rest: number[]) => undefined;
|
||||
let x: X = a => undefined; //valid
|
||||
|
||||
```
|
||||
|
||||
Functions with overloads are valid if the overload signature is compatible with its implementation signature:
|
||||
|
@ -761,7 +741,6 @@ function y(a: string, b: number): void {
|
|||
}
|
||||
y('a');
|
||||
y('a', 1);
|
||||
|
||||
```
|
||||
|
||||
Function parameter comparison succeeds if the source and target parameters are assignable to supertypes or subtypes (bivariance).
|
||||
|
@ -786,7 +765,6 @@ const getA: GetA = x => x.a;
|
|||
console.log(getA(new X('x'))); // Valid
|
||||
console.log(getA(new Y('Y'))); // Valid
|
||||
console.log(getA(new Z('z'))); // Valid
|
||||
|
||||
```
|
||||
|
||||
Enums are comparable and valid with numbers and vice versa, but comparing Enum values from different Enum types is invalid.
|
||||
|
@ -805,7 +783,6 @@ enum Y {
|
|||
const xa: number = X.A; // Valid
|
||||
const ya: Y = 0; // Valid
|
||||
X.A === Y.A; // Invalid
|
||||
|
||||
```
|
||||
|
||||
Instances of a class are subject to a compatibility check for their private and protected members:
|
||||
|
@ -827,7 +804,6 @@ class Y {
|
|||
}
|
||||
|
||||
let x: X = new Y('y'); // Invalid
|
||||
|
||||
```
|
||||
|
||||
The comparison check does not take into consideration the different inheritance hierarchy, for instance:
|
||||
|
@ -857,7 +833,6 @@ let y: Y = new Y('y');
|
|||
let z: Z = new Z('z');
|
||||
x === y; // Valid
|
||||
x === z; // Valid even if z is from a different inheritance hierarchy
|
||||
|
||||
```
|
||||
Generics are compared using their structures based on the resulting type after applying the generic parameter, only the final result is compared as a non-generic type.
|
||||
|
||||
|
@ -869,7 +844,6 @@ interface X<T> {
|
|||
let x: X<number> = { a: 1 };
|
||||
let y: X<string> = { a: 'a' };
|
||||
x === y; // Invalid as the type argument is used in the final structure
|
||||
|
||||
```
|
||||
|
||||
```typescript
|
||||
|
@ -877,7 +851,6 @@ interface X<T> {}
|
|||
const x: X<number> = 1;
|
||||
const y: X<string> = 'a';
|
||||
x === y; // Valid as the type argument is not used in the final structure
|
||||
|
||||
```
|
||||
|
||||
When generics do not have their type argument specified, all the unspecified arguments are treated as types with "any":
|
||||
|
@ -888,7 +861,6 @@ type Y = <K>(y: K) => K;
|
|||
let x: X = x => x;
|
||||
let y: Y = y => y;
|
||||
x = y; // Valid
|
||||
|
||||
```
|
||||
|
||||
Remember:
|
||||
|
@ -917,7 +889,6 @@ let g: void;
|
|||
let g1: any;
|
||||
g = 1; // Invalid, void is not assignable to or from anything expect any
|
||||
g = g1; // Valid
|
||||
|
||||
```
|
||||
|
||||
Please note that when "strictNullChecks" is enabled, "null" and "undefined" are treated similarly to "void"; otherwise, they are similar to "never".
|
||||
|
@ -940,7 +911,7 @@ TypeScript supports various types of sets:
|
|||
|
||||
Here few examples:
|
||||
|
||||
| TypScript | Set term | Example |
|
||||
| TypeScript | Set term | Example |
|
||||
| --------------------- | ---------------------- | ------------------------------------------------------------------------------- |
|
||||
| never | ∅ (empty set) | const x: never = 'x'; // Error: Type 'string' is not assignable to type 'never' |
|
||||
| | |
|
||||
|
@ -978,7 +949,6 @@ type Y = {
|
|||
};
|
||||
type XY = X | Y;
|
||||
const r: XY = { a: 'a', b: 'x' }; // Valid
|
||||
|
||||
```
|
||||
|
||||
An intersection, (T1 & T2) create a narrower set (only shared):
|
||||
|
@ -995,12 +965,11 @@ type Y = {
|
|||
type XY = X & Y;
|
||||
const r: XY = { a: 'a' }; // Invalid
|
||||
const j: XY = { a: 'a', b: 'b' }; // Valid
|
||||
|
||||
```
|
||||
|
||||
The `extends` keyword could be considered as a “subset of” in this context. It sets a constraint for a type. The extends used with a generic, take the generic as an infinite set and it will constrain it to a more specific type.
|
||||
Please note that `extends` has nothing to do with hierarchy in a OOP sense (there is no this concept in TypScript).
|
||||
TypeScript works with sets and does not have a strict hierarchy, infact, as in the example below, two types could overlap without either being a subtype of the other type (TypScript considers the structure, shape of the objects).
|
||||
Please note that `extends` has nothing to do with hierarchy in a OOP sense (there is no this concept in TypeScript).
|
||||
TypeScript works with sets and does not have a strict hierarchy, infact, as in the example below, two types could overlap without either being a subtype of the other type (TypeScript considers the structure, shape of the objects).
|
||||
|
||||
```typescript
|
||||
interface X {
|
||||
|
@ -1028,7 +997,6 @@ interface Z1 {
|
|||
const z1: Z1 = { a: 'a', b: 'b', c: 'c' };
|
||||
|
||||
const r: Z1 = z; // Valid
|
||||
|
||||
```
|
||||
|
||||
### Assign a type: Type Declarations and Type Assertions
|
||||
|
@ -1047,7 +1015,6 @@ const x: X = {
|
|||
// Type declaration
|
||||
a: 'a',
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
If the variable is not in the specified format, TypeScript will report an error. For instance:
|
||||
|
@ -1062,7 +1029,6 @@ const x: X = {
|
|||
a: 'a',
|
||||
b: 'b', // Error: Object literal may only specify known properties
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
#### Type Assertion
|
||||
|
@ -1079,7 +1045,6 @@ const x = {
|
|||
a: 'a',
|
||||
b: 'b',
|
||||
} as X;
|
||||
|
||||
```
|
||||
|
||||
In the above example, the object x is asserted to have the type X using the as keyword. This informs the TypeScript compiler that the object conforms to the specified type, even though it has an additional property b not present in the type definition.
|
||||
|
@ -1104,7 +1069,6 @@ type X = {
|
|||
b: number;
|
||||
};
|
||||
type Y = J<X>;
|
||||
|
||||
```
|
||||
|
||||
In this example, the type J<Type> uses a mapped type with a template literal to remap the keys of Type. It creates new properties with a prefix_ added to each key, and their corresponding values are functions returning the original property values.
|
||||
|
@ -1118,7 +1082,6 @@ This assertion is applied using a post-fix `!` expression operator, which tells
|
|||
```typescript
|
||||
let x: null | number;
|
||||
let y = x!; // number
|
||||
|
||||
```
|
||||
|
||||
#### Ambient Declarations
|
||||
|
@ -1139,7 +1102,6 @@ For your defined Ambient Declarations, you can import using the “triple-slash
|
|||
<!-- skip -->
|
||||
```typescript
|
||||
/// <reference path="./library-types.d.ts" />
|
||||
|
||||
```
|
||||
You can use Ambient Declarations even within JavaScript files using `// @ts-check`.
|
||||
|
||||
|
@ -1157,7 +1119,6 @@ type X = {
|
|||
const y = { a: 'a', b: 'b' };
|
||||
const x: X = y; // Valid because structural typing
|
||||
const w: X = { a: 'a', b: 'b' }; // Invalid because excess property checking
|
||||
|
||||
```
|
||||
|
||||
### Weak Types
|
||||
|
@ -1169,7 +1130,6 @@ type X = {
|
|||
a?: string;
|
||||
b?: string;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
TypeScript considers an error to assign anything to a weak type when there is no overlap, for instance, the following throws an error:
|
||||
|
@ -1184,7 +1144,6 @@ type Options = {
|
|||
const fn = (options: Options) => undefined;
|
||||
|
||||
fn({ c: 'c' }); // Invalid
|
||||
|
||||
```
|
||||
|
||||
Although not recommended, if needed, it is possible to bypass this check by using type assertion:
|
||||
|
@ -1210,7 +1169,6 @@ type Options = {
|
|||
|
||||
const fn = (options: Options) => undefined;
|
||||
fn({ c: 'c' }); // Valid
|
||||
|
||||
```
|
||||
|
||||
### Strict Object Literal Checking (Freshness)
|
||||
|
@ -1238,22 +1196,20 @@ fn(x);
|
|||
fn(y); // No errors, structurally type compatible
|
||||
|
||||
fn({ a: 'a', bx: 'b' }); // Freshness check: Invalid argument
|
||||
|
||||
```
|
||||
|
||||
### Type Inference
|
||||
|
||||
TypeScript can infer types when no annotation is provided during:
|
||||
* Variable initialization.
|
||||
* Member initialization.
|
||||
* Setting defaults for parameters.
|
||||
* Function return type.
|
||||
* Variable initialization.
|
||||
* Member initialization.
|
||||
* Setting defaults for parameters.
|
||||
* Function return type.
|
||||
|
||||
For example:
|
||||
|
||||
```typescript
|
||||
let x = 'x'; // The type inferred is string
|
||||
|
||||
```
|
||||
|
||||
The TypeScript compiler analyzes the value or expression and determines its type based on the available information.
|
||||
|
@ -1264,21 +1220,18 @@ When multiple expressions are used in type inference, TypeScript looks for the "
|
|||
|
||||
```typescript
|
||||
let x = [1, 'x', 1, null]; // The type inferred is: (string | number | null)[]
|
||||
|
||||
```
|
||||
|
||||
If the compiler cannot find the best common types, it returns a union type. For example:
|
||||
|
||||
```typescript
|
||||
let x = [new RegExp('x'), new Date()]; // Type inferred is: (RegExp | Date)[]
|
||||
|
||||
```
|
||||
|
||||
TypeScript utilizes "contextual typing" based on the variable's location to infer types. In the following example, the compiler knows that `e` is of type `MouseEvent` because of the `click` event type defined in the lib.d.ts file, which contains ambient declarations for various common JavaScript constructs and the DOM:
|
||||
|
||||
```typescript
|
||||
window.addEventListener('click', function (e) {}); // e inferred type is MouseEvent
|
||||
|
||||
```
|
||||
|
||||
### Type Widening
|
||||
|
@ -1291,7 +1244,6 @@ In the following example:
|
|||
let x = 'x'; // TypeScript infers as string, a wide type
|
||||
let y: 'y' | 'x' = 'y'; // y types is a union of literal types
|
||||
y = x; // Invalid Type 'string' is not assignable to type '"x" | "y"'.
|
||||
|
||||
```
|
||||
|
||||
TypeScript assigns `string` to `x` based on the single value provided during initialization (`x`), this is an example of widening.
|
||||
|
@ -1308,11 +1260,10 @@ For example:
|
|||
const x = 'x'; // TypeScript infers the type of x as 'x', a narrower type
|
||||
let y: 'y' | 'x' = 'y';
|
||||
y = x; // Valid: The type of x is inferred as 'x'
|
||||
|
||||
```
|
||||
|
||||
By using const to declare the variable x, its type is narrowed to the specific literal value 'x'. Since the type of x is narrowed, it can be assigned to the variable y without any error.
|
||||
The reason the type can be inferred is because const variables cannot be reassigned, so their type can be narrowed down to a specific literal type, in this case, the literal type 'x'.
|
||||
By using `const` to declare the variable x, its type is narrowed to the specific literal value 'x'. Since the type of x is narrowed, it can be assigned to the variable y without any error.
|
||||
The reason the type can be inferred is because `const` variables cannot be reassigned, so their type can be narrowed down to a specific literal type, in this case, the literal type 'x'.
|
||||
|
||||
#### const modifier on type parameters
|
||||
|
||||
|
@ -1324,7 +1275,6 @@ function identity<T>(value: T) {
|
|||
return value;
|
||||
}
|
||||
const values = identity({ a: 'a', b: 'b' }); // Type infered is: { a: string; b: string; }
|
||||
|
||||
```
|
||||
|
||||
As you can see, the properties `a` and `b` are inferred with a type of `string` .
|
||||
|
@ -1337,7 +1287,6 @@ function identity<const T>(value: T) {
|
|||
return value;
|
||||
}
|
||||
const values = identity({ a: 'a', b: 'b' }); // Type infered is: { a: "a"; b: "b"; }
|
||||
|
||||
```
|
||||
|
||||
Now we can see that the properties `a` and `b` are inferred as `const`, so `a` and `b` are treated as string literals rather than just `string` types.
|
||||
|
@ -1351,7 +1300,6 @@ const v = {
|
|||
x: 1, // Inferred type: number (widening)
|
||||
};
|
||||
v.x = 3; // Valid
|
||||
|
||||
```
|
||||
|
||||
We can make the type annotation more specific by using a union of literal types:
|
||||
|
|
Loading…
Reference in a new issue