arthurakay arthurakay - 1 month ago 11
TypeScript Question

Typescript: declare a parameter or property as one of the keys in a known object

I'm fairly new to TypeScript, and I've been trying to refactor some code.

Considering I have an object defined as such:

const Operators = {
equal: '=',
not_equal: '!=',
less: '<',
less_or_equal: '<=',
greater: '>',
greater_or_equal: '>=',
contains: '~'
};


And then I have a class defined as such:

class Query {
// I want to limit this to the keys defined in Operator
operator: string;

constructor(operator: string) {
this.operator = operator;
}

getOperatorValue: string {
return Operators[this.operator];
}
}


How can I enforce that the parameter "operator" be one of the keys of
Operators
?

I get the following error against the line inside
getOperatorValue()
:

Error: TS7017:Element implicitly has an 'any' type because type '{ equal: string; not_equal: string; less: string; less_or_equal: string; greater: string; greater...' has no index signature.


This is using Typescript 2.4.2.

Answer Source

You might be looking for the keyOf operator, introduced in 2.1 and documented with index types. Simply, function foo<T>(bar: T, key: keyof T) ensure that key will always be a known key from T. It provides an easy way to type-safely use string indexers, among other uses in the type system.

The docs show examples of using keyOf to implement a type-safe Partial class:

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
}
type Partial<T> = {
    [P in keyof T]?: T[P];
}