└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Types 2 | This document lists some common types in TypeScript and provides examples for each one. 3 | ### 4 | ## Primitive 5 | TypeScript has several basic types that you can use to define the static type for variables, function parameters, and return values. 6 | 7 | ### boolean 8 | This type represents logical values, such as true or false. 9 | ```ts 10 | let b: boolean = true; 11 | ``` 12 | ### number 13 | This type represents numeric values, such as integers and floats. 14 | ```ts 15 | let n: number = 2; 16 | ``` 17 | ### string 18 | This type represents text values. 19 | ```ts 20 | let s: string = 'a string'; 21 | ``` 22 | ### null 23 | This type represents the intentional absence of a value or an empty variable 24 | ```ts 25 | let x: null = null; 26 | ``` 27 | ### undefined 28 | This type represents the absence of a value or an uninitialized variable. 29 | ```ts 30 | let y: undefined = undefined; 31 | ``` 32 | ### symbol 33 | This type represents a unique and immutable identifier that can be used as an object key. 34 | ```ts 35 | let sym = Symbol(); 36 | let obj = { 37 | [sym]: "value" 38 | }; 39 | ``` 40 | 41 | ### bigint 42 | This type represents large integer values that cannot be represented by the number type. 43 | ```ts 44 | let big = 123n; 45 | let big2 = big + 456n; // 579n 46 | ``` 47 | 48 | ### 49 | 50 | ## Special types 51 | ### enum 52 | A named set of constant values. 53 | ```ts 54 | enum Color {Red, Green, Blue}; 55 | let c: Color = Color.Green; 56 | ``` 57 | ### any 58 | A type that can represent any value. 59 | ```ts 60 | let anything: any = 4; 61 | anything = "hello"; 62 | anything = true; 63 | ``` 64 | ### unknown 65 | A type that can represent any value, but requires type checking before using. 66 | ```ts 67 | let something: unknown = 4; 68 | something = "hello"; 69 | something = true; // need to check the type before using it 70 | ``` 71 | ### void 72 | A type that represents the absence of any value, usually used for functions that do not return anything. 73 | ```ts 74 | function log(message: string): void { 75 | console.log(message); 76 | } 77 | ``` 78 | ### never 79 | A type that represents values that never occur, such as a function that always throws an error or never returns. 80 | ```ts 81 | function error(message: string): never { 82 | throw new Error(message); 83 | } 84 | ``` 85 | 86 | ### 87 | 88 | ## Object Types 89 | 90 | ### interface 91 | A type that describes the shape of an object, such as its properties and methods. For example: 92 | ```ts 93 | interface Person { 94 | name: string; 95 | age: number; 96 | greet(): void; 97 | } 98 | ``` 99 | ### class 100 | A type that defines an object with a constructor, properties, methods, and inheritance. For example: 101 | ```ts 102 | class Animal { 103 | name: string; 104 | constructor(name: string) { 105 | this.name = name; 106 | } 107 | makeSound(): void { 108 | console.log("Generic animal sound"); 109 | } 110 | } 111 | ``` 112 | ### array 113 | A collection of values of the same type, either written as type[] or Array. 114 | ```ts 115 | let list1: number[] = [1, 2, 3]; 116 | let list2: Array = [1, 2, 3]; 117 | ``` 118 | ### tuple 119 | A fixed-length array of values of different types. 120 | ```ts 121 | let pair: [string, number] = ["Bob", 42]; 122 | ``` 123 | ### object 124 | A type that represents any non-primitive value. 125 | ```ts 126 | let person: object = {name: "Charlie", age: 25}; 127 | ``` 128 | ### function 129 | A type that represents a callable object with parameters and a return value. 130 | ```ts 131 | let add: (x: number, y: number) => number = (x, y) => x + y; 132 | ``` 133 | 134 | ### 135 | ## Union and intersection 136 | ### Intersection 137 | These are types that combine multiple types into one, using the & operator.\ 138 | For example, A & B is a type that has all the properties of both A and B. 139 | ```ts 140 | type Person = { name: string; age: number }; 141 | type Employee = { id: number; department: string }; 142 | type Manager = Person & Employee; // a type that has all the properties of Person and Employee 143 | ``` 144 | ### Union 145 | These are types that allow a value to be one of several types, using the | operator.\ 146 | For example, A | B is a type that can be either A or B. 147 | ```ts 148 | type Shape = Circle | Square | Triangle; // a type that can be either Circle, Square, or Triangle 149 | ``` 150 | ### 151 | ## Generic 152 | **generic:** A type that can take a type parameter and reuse it in some way. 153 | ```ts 154 | function identity(value: T): T { 155 | return value; 156 | } 157 | ``` 158 | This function can work with any type T and return the same type as the input. It can be called with different types. 159 | ```ts 160 | let number = identity(42); // T is number 161 | let string = identity("Hello"); // T is string 162 | let array = identity([1, 2, 3]); // T is number[] 163 | ``` 164 | ### 165 | ## Utility 166 | These are built-in types that provide some common type transformations, such as Partial, Required, Readonly, etc. 167 | ### Partial 168 | For example: if you have an interface Todo with three properties, you can use Partial to create a type that can have any combination of those properties. 169 | ```ts 170 | interface Todo { 171 | title: string; 172 | description: string; 173 | completed: boolean; 174 | } 175 | 176 | let todo1: Partial = {}; // valid 177 | let todo2: Partial = { title: "Learn TypeScript" }; // valid 178 | let todo3: Partial = { title: "Learn TypeScript", completed: true }; // valid 179 | let todo4: Partial = { title: "Learn TypeScript", priority: 1 }; // invalid, priority is not a property of Todo 180 | ``` 181 | ### Required 182 | For example: if you have an interface Person with two optional properties, you can use Required to create a type that requires both properties. 183 | ```ts 184 | interface Person { 185 | name?: string; 186 | age?: number; 187 | } 188 | 189 | let person1: Required = {}; // invalid, name and age are required 190 | let person2: Required = { name: "Alice" }; // invalid, age is required 191 | let person3: Required = { name: "Alice", age: 21 }; // valid 192 | let person4: Required = { name: "Alice", age: 21, location: "New York" }; // invalid, location is not a property of Person 193 | ``` 194 | ### Readonly 195 | For example, if you have an interface Point with two properties, you can use Readonly to create a type that prevents modifying those properties. 196 | ```ts 197 | interface Point { 198 | x: number; 199 | y: number; 200 | } 201 | 202 | let point1: Readonly = { x: 10, y: 20 }; // valid 203 | point1.x = 15; // invalid, x is readonly 204 | point1.y++; // invalid, y is readonly 205 | point1.z = 30; // invalid, z is not a property of Point 206 | ``` 207 | ### ReturnType 208 | For example: if you have a function type that returns a number, you can use ReturnType to create a type that is the same as the return type of the function. 209 | ```ts 210 | type Adder = (a: number, b: number) => number; 211 | 212 | let result1: ReturnType = 10; // valid 213 | let result2: ReturnType = "hello"; // invalid, string is not assignable to number 214 | ``` 215 | ### Parameters 216 | For example, if you have a function type that takes two parameters of type string and number, you can use Parameters to create a tuple type that represents the parameter types 217 | of the function. 218 | ```ts 219 | type Logger = (message: string, level: number) => void; 220 | 221 | let params1: Parameters = ["error", 1]; // valid 222 | let params2: Parameters = [1, "error"]; // invalid, number is not assignable to string and vice versa 223 | ``` 224 | ### Pick 225 | For example: if you have an interface User with four properties, you can use Pick to create a type that only has the name and email properties. 226 | ```ts 227 | interface User { 228 | name: string; 229 | email: string; 230 | password: string; 231 | role: string; 232 | } 233 | 234 | let user1: Pick = {}; // invalid, name and email are required 235 | let user2: Pick = { name: "Bob", email: "bob@example.com" }; // valid 236 | let user3: Pick = { name: "Bob", email: "bob@example.com", password: "secret" }; // invalid, password is not a property of Pick 237 | ``` 238 | ### Omit 239 | For example: if you have an interface User with four properties, you can use Omit to create a type that excludes the password and role properties. 240 | ```ts 241 | interface User { 242 | name: string; 243 | email: string; 244 | password: string; 245 | role: string; 246 | } 247 | 248 | let user1: Omit = {}; // invalid, name and email are required 249 | let user2: Omit = { name: "Bob", email: "bob@example.com" }; // valid 250 | let user3: Omit = { name: "Bob", email: "bob@example.com", password: "secret" }; // invalid, password is not a property of Omit 251 | ``` 252 | ### Exclude 253 | For example: if you have a type Animal with four values, you can use Exclude to create a type that excludes the cat and dog values. 254 | ```ts 255 | type Animal = "cat" | "dog" | "bird" | "fish"; 256 | 257 | let animal1: Exclude = "cat"; // invalid, cat is excluded 258 | let animal2: Exclude = "bird"; // valid 259 | let animal3: Exclude = "lion"; // invalid, lion is not a value of Animal 260 | ``` 261 | ### Record 262 | For example: if you have a type Color with three values, you can use Record to create an object type that maps each color to a string. 263 | ```ts 264 | type Color = "red" | "green" | "blue"; 265 | 266 | let colorMap: Record = {}; // invalid, colorMap must have properties for each color 267 | let colorMap: Record = { red: "#FF0000", green: "#00FF00", blue: "#0000FF" }; // valid 268 | let colorMap: Record = { red: "#FF0000", green: "#00FF00", blue: "#0000FF", yellow: "#FFFF00" }; // invalid, yellow is not a value of Color 269 | ``` 270 | 271 | ### Awaited 272 | This type is meant to model operations like await in async functions, or the .then() method on Promises - specifically, the way that they recursively unwrap Promises 273 | ```ts 274 | type A = Awaited>; // A is string 275 | type B = Awaited>>; // B is number 276 | ``` 277 | ### 278 | ## Custom type 279 | There are many TypeScript types that are not built-in utility types, but can be defined as custom types using the type keyword and other type operators. 280 | Some examples of custom types are: 281 | ### PickByValue 282 | This type constructs a type by picking the properties from Type that have values of ValueType. 283 | ```ts 284 | type Test = { 285 | includeMe: 'a'; 286 | andMe: 'a'; 287 | butNotMe: 'b'; 288 | orMe: 'b'; 289 | }; 290 | 291 | type PickByValue = Pick; 292 | 293 | type TestA = PickByValue; // { includeMe: "a"; andMe: "a" } 294 | ``` 295 | 296 | ### PickByValueExact 297 | This type constructs a type by picking the properties from Type that have values exactly equal to ValueType. 298 | ```ts 299 | type Test = { 300 | includeMe: 'a'; 301 | andMe: 'a' as const; 302 | butNotMe: 'b'; 303 | orMe: 'b' as const; 304 | }; 305 | 306 | type PickByValueExact = Pick; 307 | 308 | type TestA = PickByValueExact; // { includeMe: "a" } 309 | ``` 310 | 311 | ### OmitByValue 312 | This type constructs a type by picking the properties from Type that do not have values of ValueType. 313 | ```ts 314 | type Test = { 315 | includeMe: 'a'; 316 | andMe: 'a'; 317 | butNotMe: 'b'; 318 | orMe: 'b'; 319 | }; 320 | 321 | type OmitByValue = Omit; 322 | 323 | type TestB = OmitByValue; // { butNotMe: "b"; orMe: "b" } 324 | 325 | ``` 326 | 327 | ### OmitByValueExact 328 | This type constructs a type by picking the properties from Type that do not have values exactly equal to ValueType. 329 | ```ts 330 | type Test = { 331 | includeMe: 'a'; 332 | andMe: 'a' as const; 333 | butNotMe: 'b'; 334 | orMe: 'b' as const; 335 | }; 336 | 337 | type OmitByValueExact = Omit; 338 | 339 | type TestB = OmitByValueExact; // { andMe: "a"; butNotMe: "b"; orMe: "b" } 340 | ``` 341 | 342 | ### Intersection 343 | This type constructs a type that is the intersection of T and U. It is similar to the built-in & operator, but works with object types. 344 | ```ts 345 | type A = { x: number; y: number }; 346 | type B = { y: string; z: boolean }; 347 | 348 | type C = A & B; // { x: number; y: number & string; z: boolean } 349 | ``` 350 | 351 | ### Diff 352 | This type constructs a type that is the difference of T and U. It is similar to the built-in Exclude utility, but works with object types. 353 | ```ts 354 | type A = { x: number; y: number; z: boolean }; 355 | type B = { x: string; z: boolean }; 356 | 357 | type Diff = T extends U ? never : T; 358 | 359 | type C = Diff; // { y: number } 360 | ``` 361 | 362 | ### Subtract 363 | This type constructs a type that is T without T1. It is similar to Diff, but preserves optional modifiers. 364 | ```ts 365 | type A = { x: number; y: number; z: boolean }; 366 | type B = { x: string; z: boolean }; 367 | 368 | type Subtract = Omit; 369 | 370 | type C = Subtract; // { y: number } 371 | ``` 372 | 373 | ### Overwrite 374 | This type constructs a type that is T with U overwriting existing properties. It is similar to Intersection, but preserves optional modifiers. 375 | ```ts 376 | type A = { x: number; y: number; z: boolean }; 377 | type B = { x: string; z: boolean }; 378 | 379 | type Overwrite = Omit & U; 380 | 381 | type C = Overwrite; // { x: string; y: number; z: boolean } 382 | ``` 383 | 384 | ### Assign 385 | This type constructs a type that is T with U merged into it. It is similar to Object.assign(), but works with types. 386 | ```ts 387 | type A = { x?: number; y?: number }; 388 | type B = { x?: string; z?: boolean }; 389 | 390 | type Assign = T & Omit; 391 | 392 | type C = Assign; // { x?: number | undefined; y?: number | undefined; z?: boolean | undefined } 393 | 394 | ``` 395 | 396 | ### ValuesType 397 | This type constructs a union of all values in an object or array T. 398 | ```ts 399 | type Person = { 400 | name: string; 401 | age: number; 402 | }; 403 | 404 | type ValuesType = T[keyof T]; 405 | 406 | type PersonValues = ValuesType; // string | number 407 | ``` 408 | 409 | ### InstanceType 410 | This type constructs a type consisting of the instance type of constructor function T (built-in). 411 | ```ts 412 | class Point { 413 | constructor(public x: number, public y: number) {} 414 | } 415 | 416 | type PointInstance = InstanceType; // Point 417 | 418 | let p: PointInstance = new Point(10, 20); // OK 419 | ``` 420 | 421 | ### Unionize 422 | This type constructs a union of all possible variants of an object or array T. 423 | ```ts 424 | type Person = { 425 | name: string; 426 | age: number; 427 | }; 428 | 429 | type Unionize = { [K in keyof T]: { [P in K]: T[P] } }[keyof T]; 430 | 431 | type PersonUnion = Unionize; // { name: string } | { age: number } 432 | ``` 433 | 434 | ### Brand 435 | This type constructs a branded primitive based on T and U. It can be used to create nominal types in TypeScript. 436 | ```ts 437 | type Brand = T & { __brand: U }; 438 | 439 | type Meter = Brand; 440 | type Second = Brand; 441 | 442 | let distance: Meter = 100 as Meter; // OK 443 | let time: Second = 10 as Second; // OK 444 | 445 | distance = time; // Error 446 | time = distance; // Error 447 | ``` 448 | 449 | ### UnionToIntersection 450 | This type converts a union U to an intersection. It can be used to infer common properties from a union. 451 | ```ts 452 | type A = { x: number; y: number }; 453 | type B = { y: string; z: boolean }; 454 | 455 | type UnionToIntersection = 456 | (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; 457 | 458 | type C = UnionToIntersection; // { x: number; y: number & string; z: boolean } 459 | ``` 460 | ### 461 | ## Mapped 462 | These are types that create new types based on the shape of existing types, using a syntax similar to object literals.\ 463 | For example: { [P in keyof T]: T[P] } is a type that maps over the properties of T and preserves their types. 464 | ```ts 465 | // a type that has properties "a", "b", and "c" with values of type number 466 | type Keys = "a" | "b" | "c"; 467 | type Obj = { [K in Keys]: number }; 468 | ``` 469 | **Indexed access types:** These are types that access the type of a property of another type by using the [] notation. They use a syntax like T[K] where T is an object type and K is a key type. 470 | ```ts 471 | type Person = { 472 | name: string; 473 | age: number; 474 | }; 475 | 476 | type Name = Person["name"]; // string 477 | type Age = Person["age"]; // number 478 | ``` 479 | 480 | **Index signatures:** These are types that declare the types of properties that have not been declared ahead of time. They use a syntax like { [key: K]: T } where K is a string, number, or symbol, and T is any type. 481 | ```ts 482 | type Dictionary = { 483 | [key: string]: string; // index signature for string keys 484 | }; 485 | 486 | type ArrayLike = { 487 | [index: number]: any; // index signature for numeric indices 488 | }; 489 | 490 | ``` 491 | 492 | **keyof type operator:** This is an operator that returns a union of literal types for each property name in an object type. It uses a syntax like keyof T where T is an object type 493 | ```ts 494 | type Point = { 495 | x: number; 496 | y: number; 497 | }; 498 | 499 | type Keys = keyof Point; // "x" | "y" 500 | 501 | ``` 502 | **Key remapping via as:** This is a feature that allows re-mapping keys in mapped types with an as clause. It uses a syntax like { [P in K as N]: T } where P is a property name, K is a union of property names, N is a new property name, and T is a type. 503 | ```ts 504 | type Person = { 505 | name: string; 506 | age: number; 507 | }; 508 | 509 | type UpperPerson = { 510 | [K in keyof Person as Uppercase]: Person[K]; // { NAME: string; AGE: number } 511 | }; 512 | ``` 513 | ### 514 | ## Guards and conditional types 515 | 516 | ### Type guards 517 | Type guards are a way of narrowing down the type of a variable or a parameter based on some condition. Type guards can help you write more type-safe and robust code by avoiding errors and bugs related to incorrect types. 518 | ```ts 519 | function printLength(x: any) { 520 | if (typeof x === "string") { 521 | // x is narrowed to string 522 | console.log(x.length); 523 | } else { 524 | // x is narrowed to exclude string 525 | console.log("Not a string"); 526 | } 527 | } 528 | ``` 529 | ### Conditional 530 | Conditional types are a way of creating types that depend on other types. They use a syntax similar to the ternary operator in JavaScript: T extends U ? X : Y. This means that if type T is assignable to type U, then the conditional type is X, otherwise it is Y. 531 | 532 | ```ts 533 | type IsString = T extends string ? true : false; 534 | 535 | type E = IsString; // true 536 | type F = IsString; // false 537 | 538 | ``` 539 | 540 | 541 | 542 | 543 | --------------------------------------------------------------------------------