Skip to content

Commit 99f082c

Browse files
committed
feat: Add TypeScript concepts and examples to README.md
1 parent a524d3a commit 99f082c

File tree

1 file changed

+323
-0
lines changed

1 file changed

+323
-0
lines changed

README.md

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,24 @@ This repository contains a list of TypeScript concepts, examples. It is a guide
3131
- [Triple-Slash Directives](#triple-slash-directives)
3232
- [Type Checking JavaScript Files](#type-checking-javascript-files)
3333
- [Utility Types](#utility-types)
34+
- [Type Assertions](#type-assertions)
35+
- [Type Guards](#type-guards)
36+
- [Tuple Types](#tuple-types)
37+
- [Index Signatures](#index-signatures)
38+
- [Mapped Types](#mapped-types)
39+
- [Conditional Types](#conditional-types)
40+
- [Union and Intersection Types](#union-and-intersection-types)
41+
- [Type Predicates](#type-predicates)
42+
- [Template Literal Types](#template-literal-types)
43+
- [Keyof Type Operator](#keyof-type-operator)
44+
- [Type Narrowing](#type-narrowing)
45+
- [Call Signatures](#call-signatures)
46+
- [Discriminated Unions](#discriminated-unions)
47+
- [Type Inference in Generic Constraints](#type-inference-in-generic-constraints)
48+
- [Non-null Assertion Operator](#non-null-assertion-operator)
49+
- [Satisfies Operator](#satisfies-operator)
50+
- [Method Signatures](#method-signatures)
51+
- [Abstract Classes](#abstract-classes)
3452

3553
## Introduction
3654

@@ -451,6 +469,311 @@ let person: ReadonlyPerson = {
451469
person.name = 'Jane Doe'; // Error: Cannot assign to 'name' because it is a read-only property
452470
```
453471

472+
## Type Assertions
473+
474+
Type assertions allow you to tell TypeScript that you know more about the type of a value than it does. It's like a type cast but has no runtime impact.
475+
476+
```typescript
477+
let someValue: unknown = "Hello World";
478+
let strLength: number = (someValue as string).length;
479+
480+
// Alternatively using angle bracket syntax
481+
let strLength2: number = (<string>someValue).length;
482+
```
483+
484+
## Type Guards
485+
486+
Type guards are expressions that perform runtime checks to guarantee the type in a certain scope.
487+
488+
```typescript
489+
function isString(value: unknown): value is string {
490+
return typeof value === "string";
491+
}
492+
493+
function processValue(value: number | string) {
494+
if (isString(value)) {
495+
console.log(value.toUpperCase()); // TypeScript knows value is a string
496+
} else {
497+
console.log(value.toFixed(2)); // TypeScript knows value is a number
498+
}
499+
}
500+
```
501+
502+
## Tuple Types
503+
504+
Tuples are arrays with a fixed number of elements whose types are known.
505+
506+
```typescript
507+
let tuple: [string, number] = ["hello", 10];
508+
console.log(tuple[0].substring(1)); // "ello"
509+
console.log(tuple[1].toFixed(1)); // "10.0"
510+
```
511+
512+
## Index Signatures
513+
514+
Index signatures allow you to create objects with flexible property names.
515+
516+
```typescript
517+
interface StringMap {
518+
[key: string]: string;
519+
}
520+
521+
let map: StringMap = {
522+
"foo": "bar",
523+
"baz": "qux"
524+
};
525+
```
526+
527+
## Mapped Types
528+
529+
Mapped types allow you to create new types based on old ones by transforming properties.
530+
531+
```typescript
532+
type Readonly<T> = {
533+
readonly [P in keyof T]: T[P];
534+
};
535+
536+
interface Person {
537+
name: string;
538+
age: number;
539+
}
540+
541+
type ReadonlyPerson = Readonly<Person>;
542+
```
543+
544+
## Conditional Types
545+
546+
Conditional types select one of two possible types based on a condition.
547+
548+
```typescript
549+
type TypeName<T> =
550+
T extends string ? "string" :
551+
T extends number ? "number" :
552+
T extends boolean ? "boolean" :
553+
"object";
554+
555+
type T0 = TypeName<string>; // "string"
556+
type T1 = TypeName<number>; // "number"
557+
```
558+
559+
## Union and Intersection Types
560+
561+
Union types allow a value to be one of several types, while intersection types combine multiple types into one.
562+
563+
```typescript
564+
// Union type
565+
type StringOrNumber = string | number;
566+
let value: StringOrNumber = "hello";
567+
value = 42; // also valid
568+
569+
// Intersection type
570+
interface HasName { name: string; }
571+
interface HasAge { age: number; }
572+
type Person = HasName & HasAge;
573+
574+
let person: Person = {
575+
name: "John",
576+
age: 25
577+
};
578+
```
579+
580+
## Type Predicates
581+
582+
Type predicates are special return type annotations that declare a type guard.
583+
584+
```typescript
585+
function isFish(pet: Fish | Bird): pet is Fish {
586+
return (pet as Fish).swim !== undefined;
587+
}
588+
589+
let pet: Fish | Bird = getRandomPet();
590+
if (isFish(pet)) {
591+
pet.swim(); // TypeScript knows pet is Fish
592+
} else {
593+
pet.fly(); // TypeScript knows pet is Bird
594+
}
595+
```
596+
597+
## Template Literal Types
598+
599+
Template literal types build on string literal types and allow creating complex string patterns.
600+
601+
```typescript
602+
type World = "world";
603+
type Greeting = `hello ${World}`; // type Greeting = "hello world"
604+
605+
type EmailLocaleIDs = "welcome_email" | "email_heading";
606+
type FooterLocaleIDs = "footer_title" | "footer_sendoff";
607+
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;
608+
```
609+
610+
## Keyof Type Operator
611+
612+
The keyof operator queries the key type of an object type.
613+
614+
```typescript
615+
interface Person {
616+
name: string;
617+
age: number;
618+
location: string;
619+
}
620+
621+
type PersonKeys = keyof Person; // "name" | "age" | "location"
622+
623+
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
624+
return obj[key];
625+
}
626+
```
627+
628+
## Type Narrowing
629+
630+
Type narrowing is the process of refining types to more specific ones after type checks.
631+
632+
```typescript
633+
function padLeft(padding: number | string, input: string) {
634+
if (typeof padding === "number") {
635+
return " ".repeat(padding) + input; // TypeScript knows padding is number
636+
}
637+
return padding + input; // TypeScript knows padding is string
638+
}
639+
```
640+
641+
## Call Signatures
642+
643+
Call signatures define how functions can be called, including parameters and return types.
644+
645+
```typescript
646+
interface CalculatorFunction {
647+
(x: number, y: number): number;
648+
mode?: "add" | "subtract";
649+
}
650+
651+
const add: CalculatorFunction = (x, y) => x + y;
652+
add.mode = "add";
653+
654+
console.log(add(5, 3)); // 8
655+
```
656+
657+
## Discriminated Unions
658+
659+
Discriminated unions are a pattern where you use a common property to narrow down the type of an object.
660+
661+
```typescript
662+
interface Circle {
663+
kind: "circle";
664+
radius: number;
665+
}
666+
667+
interface Square {
668+
kind: "square";
669+
sideLength: number;
670+
}
671+
672+
type Shape = Circle | Square;
673+
674+
function getArea(shape: Shape) {
675+
switch (shape.kind) {
676+
case "circle":
677+
return Math.PI * shape.radius ** 2;
678+
case "square":
679+
return shape.sideLength ** 2;
680+
}
681+
}
682+
```
683+
684+
## Type Inference in Generic Constraints
685+
686+
TypeScript can infer types in generic constraints based on the usage context.
687+
688+
```typescript
689+
function getProperty<T, K extends keyof T>(obj: T, key: K) {
690+
return obj[key];
691+
}
692+
693+
const person = {
694+
name: "John",
695+
age: 30
696+
};
697+
698+
const name = getProperty(person, "name"); // TypeScript infers string type
699+
const age = getProperty(person, "age"); // TypeScript infers number type
700+
```
701+
702+
## Non-null Assertion Operator
703+
704+
The non-null assertion operator (!) tells TypeScript that a value cannot be null or undefined.
705+
706+
```typescript
707+
function getValue(): string | undefined {
708+
return "hello";
709+
}
710+
711+
const value = getValue()!; // TypeScript treats value as string
712+
console.log(value.length); // No error
713+
```
714+
715+
## Satisfies Operator
716+
717+
The satisfies operator ensures a value matches a type without widening its inference.
718+
719+
```typescript
720+
type RGB = readonly [red: number, green: number, blue: number];
721+
type Color = RGB | string;
722+
723+
const palevioletred = [219, 112, 147] satisfies RGB;
724+
// Type is exactly [219, 112, 147], not number[]
725+
```
726+
727+
## Method Signatures
728+
729+
Method signatures define how methods within interfaces or types should be structured.
730+
731+
```typescript
732+
interface DateTime {
733+
toUTC(): Date;
734+
toString(format?: string): string;
735+
compare(other: DateTime): number;
736+
}
737+
738+
class MyDateTime implements DateTime {
739+
toUTC(): Date {
740+
return new Date();
741+
}
742+
toString(format?: string): string {
743+
return format ? "formatted date" : "default format";
744+
}
745+
compare(other: DateTime): number {
746+
return 0;
747+
}
748+
}
749+
```
750+
751+
## Abstract Classes
752+
753+
Abstract classes provide a base class that other classes can extend from, with some implementation details left undefined.
754+
755+
```typescript
756+
abstract class Animal {
757+
abstract makeSound(): void;
758+
759+
move(): void {
760+
console.log("Moving...");
761+
}
762+
}
763+
764+
class Dog extends Animal {
765+
makeSound(): void {
766+
console.log("Woof!");
767+
}
768+
}
769+
770+
// Cannot instantiate abstract class
771+
// const animal = new Animal(); // Error
772+
const dog = new Dog();
773+
dog.makeSound(); // "Woof!"
774+
dog.move(); // "Moving..."
775+
```
776+
454777
## License
455778

456779
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

0 commit comments

Comments
 (0)