Index types (TypeScript)
Some examples of TypeScript index types and how to use them
Index operators
Index type query operator: keyof
interface Test {
propA: number;
propB: string;
}
type TestKey = keyof Test;
// type TestKey = "propA" | "propB"
Indexed access operator: T[K]
Can be used in generic context to indicate property types
Example (adapted from Index types ):
interface Test {
propA: number;
propB: string;
}
function getProperty<T, K extends keyof T>(o: T, propertyName: K): T[K] {
return o[propertyName]; // o[propertyName] is of type T[K]
}
const test: Test = { propA: 1, propB: "b" };
getProperty(test, "propA"); // type number
getProperty(test, "propB"); // type string
Index signatures
Can be used to specify structure of object with arbitrary property names
interface IndexSignature {
[key: string]: boolean | number;
a: boolean;
b: number;
}
function test(input: IndexSignature) {
input.a // type boolean
input.b // type number
input.c // type boolean | number;
}
Can also be used with generics:
interface GenericIndexSignature<T> {
[key: string]: T;
}
function test(input: GenericIndexSignature<number>) {
input.c // type number;
input.d // type number;
}
Use case: mapped types
Mapped types = new types based on other types
Readonly
and Partial
Implementations (already provided by TypeScript language):
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
Example:
interface Person {
name: string;
age: number;
}
type ReadonlyPerson = Readonly<Person>;
// type ReadonlyPerson = { readonly name: string; readonly age: number; }
type PartialPerson = Partial<Person>;
// type PartialPerson = { name?: string | undefined; age? : number | undefined; }
Pick
Implementation (already provided by TypeScript language):
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Example:
interface Test {
propA: string;
propB: number;
propC: boolean;
}
type Picked = Pick<Test, "propA" | "propC">;
// type Picked = { propA: string; propC: boolean; }
Use case: dictionaries with enum or type union keys
Example with enum keys:
enum TestEnum {
First = "First",
Second = "Second",
Third = "Third"
}
type DictionaryWithAllKeys = { [key in TestEnum]: number; };
type DictionaryWithSomeKeys = { [key in TestEnum]?: number; };
// error: property 'Third' is missing
const testAllKeys: DictionaryWithAllKeys = {
First: 1,
Second: 2
}
const testSomeKeys: DictionaryWithSomeKeys = {
First: 1,
Second: 2
}
Example with type union keys:
type TestUnion = "First" | "Second" | "Third";
type DictionaryWithAllKeys = { [key in TestUnion]: number; };
type DictionaryWithSomeKeys = { [key in TestUnion]?: number; };
// error: property 'Third' is missing
const testAllKeys: DictionaryWithAllKeys = {
First: 1,
Second: 2
}
const testSomeKeys: DictionaryWithSomeKeys = {
First: 1,
Second: 2
}