TypeScript Useful Types
npm install ts-it-types
All types together in ts_it_types.ts
Map types are types with key-value structure.
StringMap is dictionary type.
import { StringMap } from "ts-it-types";
// Only string value enable
const UserData: StringMap = {
"login": "guest",
"password": "pipe"
}
ObjectMap is map with any type values.
import { ObjectMap } from "ts-it-types";
// Any value available
const BigData: ObjectMap = {
"array": ["0", "1", "2"],
"map": {
"key1": "value1",
"key2": "value2"
}
}
MapQualifier is builder for custom map type.
Short name of MapQualifier is MapQ
<T> value type
import { MapQ } from "ts-it-types";
// Create your own Map Type
type CustomMap = MapQ<number[]>
// Only array of number values enable
const NumbersData: CustomMap = {
"0": [0, 1, 2],
"3": [3, 4, 5]
}
Range types are set of numbers. Using it, you can get free set of numbers.
Type Script 3.4 do not have BuildIn type or capability to declare range numbers type.
It might look like this: type CustomRange = 3..23; for example, but not yet..
All range are declared with first letter 'R' and numbers from 1 to 1000 included.
For example, range with 0 to 10 (included) is R10, range from 0 to 50 (included) is R50, and so on.
Declared range with postfix 'n' make exclude last number from range.
For example, range with 0 to 10 (excluded) is R10n, range from 0 to 50 (excluded) is R50n, and so on.
import { R24n, R60n, R1000n } from "ts-it-types";
// [0..23) Hour type
type Hour = R24n;
// [0..60) Minute type
type Minute = R60n;
// [0..60) Second type
type Second = R60n;
// [0..1000) MilliSecond type
type MilliSecond = R1000n;
RangeQualifier is builder for custom range type.
Qualifier need to declare free range, for example from 17 to 23.
Short name of RangeQualifier is RQ
<From> from range
<To> to range
import { R17n, R23, R50n, R100n, RQ } from "ts-it-types";
// [17 .. 23] Include all numbers from 17 to 23
type R_17_to_23 = RQ<R17n, R23>;
// [50 .. 100) Include all numbers from 50 to 99. Attention: 100 - excluded
type R_50_to_100n = RQ<R50n, R100n>;
Buildin overload are types with extra features of buildin TypeScript types.
GetNames is type to extract properties name, using type filter to include or exclude some names.
<FromType> type to analyze
<KeepType> type to keep. Default is any - all types be included
<Include> way of analyzing. true - include, false - exclude. Default is true.
Extra for keyof T.
import { GetNames } from "ts-it-types";
class SimpleClass {
static ZERO = 0;
readonly one: string = "1";
readonly two: string = "2";
readonly three: number = 3;
getOne(): string {
return this.one;
}
getTwo(): string {
return this.two;
}
}
// SC - SimpleClass
// be: "one" | "two" | "three" | "getOne" | "getTwo"
type SC_AllNames = GetNames<SimpleClass>; // like keyof SimpleClass
// be: "one" | "two"
type SC_StringNames = GetNames<SimpleClass, string>;
// be: "getOne" | "getTwo"
type SC_FunctionNames = GetNames<SimpleClass, Function>;
// be: "three" | "getOne" | "getTwo"
type SC_NonStringNames = GetNames<SimpleClass, string, false>;
// be: "one" | "two" | "three" | "getOne" | "getTwo" | "prototype" | "ZERO"
type SC_AllNamesWithStatic = GetNames<SimpleClass & typeof SimpleClass>;
LoseNames is type to extract properties name, using type filter to exclude some names.
LoseNames vice versa of GetNames
<FromType> type to analyze
<IgnoreType> type to ignore
Extra for keyof T.
import { LoseNames } from "ts-it-types";
type Person = {
age: number;
name: string;
lastName: string;
}
// P is Person
// be: "age"
type P_Age = LoseNames<Person, string>;
// be: "name" | "lastName"
type P_Names = LoseNames<Person, number>;
Maybe is type to define part of code which can contains value or value is absent.
import { Maybe } from "ts-it-types";
function processData(command: string): Maybe<string> {
if (command === "start") {
// to be some code here
return "start:ok"; // if command is start - get some usuful result
}
if (command === "stop") {
// to be some code here
console.log("stop now"); // if command is stop - nothing return;
}
}
TypeSelector is type to select one of two types. Its usuful when some interface or type generates 2 linked types.
For example, Server fetch data and Client model data.
<State> true or false state
<FirstType> to be type on true
<SecondType> to be type on false
import { TypeSelector } from "ts-it-types";
/** Human readable alias on true */
type ServerData = true;
/** Human readable alias on false */
type ClientData = false;
interface UserResponse<K extends boolean> {
/** User Name */
name: string;
/** User Status: server send status as number 0, 1, 2. But here useful constant "NEW", "ACTIVE" or "BLOCK" */
status: TypeSelector<K, 0 | 1 | 2, string>
}
/** After fetch data */
interface UserDto extends UserResponse<ServerData> {}
/** After PROCESS fetched data */
interface UserModel extends UserResponse<ClientData> {}
const UserStatus = {
0: "NEW",
1: "ACTIVE",
2: "BLOCKED",
}
function loadUsers(): UserModel[] {
return fetchEmulator("/users").map(userDto => {
return {...userDto, status: UserStatus[userDto.status]};
});
}
function fetchEmulator(url: string): UserDto[] {
return [{
name: "Evg Pal",
status: 0 // to be "NEW" on client side
}, {
name: "Joh Dri",
status: 1 // to be "ACTIVE" on client side
}];
}
Statement control is way to control some block of code which can be changed in future
UnreachableStatementError is error which must be throw in unreachable part of code.
Code is unreachable now but not in the future. So you control changes which will happens.
Short name of UnreachableStatementError is NeverError
UnreachableStatementError declaration
import { NeverError } from "ts-it-types";
enum Step {
STEP_1,
STEP_2,
// try to uncomment, get error at compile time
// STEP_3 // >> Argument of type 'Step.STEP_3' is not assignable to parameter of type 'never'
}
class StepWizard {
// if statement control
buildPane(step: Step): void {
if (step === Step.STEP_1) {
console.log("some code for step 1");
return;
}
if (step === Step.STEP_2) {
console.log("some code for step 2");
return;
}
// Control statement in future. If anybody add NEW step, it part of code will be broken
throw new NeverError(step); // >> error here if uncomment STEP_3
}
// switch statement control
getStepName(step: Step): string {
switch (step) {
case Step.STEP_1: return "step_1"
case Step.STEP_2: return "step_2"
default:
// Control statement in future. If anybody add NEW step, it part of code will be broken
throw new NeverError(step); // >> error here if uncomment STEP_3
}
}
}
Tuple utility types
Prepend is a type of pushing a value in the begining of an array
<Tuple> array of data
<Addend> adding value
import { Prepend } from "ts-it-types";
type DirectNumbers = ["1", "2", "3"];
// be: ["0", "1", "2", "3"]
type DirectNumbersWith0 = Prepend<DirectNumbers, "0">;
Reverse is a type to reverse array
<Tuple> array of data
import { Reverse } from "ts-it-types";
type DirectNumbers = ["1", "2", "3"];
// be: ["3", "2", "1"]
type ReverseNumbers = Reverse<DirectNumbers>;
TupleOf is a type to convert union to array
<T> union of string keys
import { TupleOf } from "ts-it-types";
interface Person {
firstName: string;
lastName: string;
position: string;
}
// be: "firstName" | "lastName" | "position"
type PersonFieldUnion = keyof Person;
// be: ["firstName", "lastName", "position"]
type PersonFieldTuple = TupleOf<PersonFieldUnion>;
UnionOf is a type to convert array to union
<Tuple> array of data
<Union> initial union value. default never
import { UnionOf } from "ts-it-types";
// be: "firstName" | "lastName" | "position"
type PersonFieldUnion = UnionOf<["firstName", "lastName", "position"]>;