interface Keys {
[key: string]: any
}
const obj: Keys = {
trimDescription(text: string, length: number): string {
return text.length > length ? text.substrin
interface Keys {
[key: string]: (text: string, length: number) => string;
}
const obj: Keys = {
trimDescription(text: string, length: number): string {
return text.length > length ? text.substring(0, length - 3) + '...' : text
}
}
Object.keys(obj).forEach(key => {
console.log(obj[key])
})
It all dependes in what you need your interface for. The usual is to represent the shape of your object with an interface and therefore explicitly type all the methods and then let the object "implement" it:
interface Keys {
trimDescription(text: string, length: number): string;
makeUppercase(description: string, active: boolean): string;
}
const obj: Keys = {
trimDescription(text, length) {
return text.length > length ? text.substring(0, length - 3) + '...' : text;
},
makeUppercase(description, active) {
// ...
},
};
(Object.keys(obj) as (keyof Keys)[]).forEach(key => {
console.log(obj[key]);
});
I guess an index signature is not what you want. There is no need for an index signature unless you need some kind of "bag" of properties of some type, then all your properties must conform to that signature.
Also you can infer the type from the object you create:
const obj = {
trimDescription(text: string, length: number): string {
return text.length > length ? text.substring(0, length - 3) + '...' : text;
},
makeUppercase(description: string, active: boolean): string {
// ...
},
};
// Inferred from the implict shape of the object
type Keys = typeof obj;
(Object.keys(obj) as (keyof Keys)[]).forEach(key => {
console.log(obj[key]);
});
playground
Maybe you should consider to use a class.
The problem with Object.keys()
is that it returns the type Array<string>
, but string
cannot index an object without an index signature. See here for the rationale. The type of the keys of a given object of type T
is keyof T
, so with (Object.keys(obj) as (keyof Keys)[])
I am telling TypeScript that "interprets" the array of keys as type Array<keyof Keys>
so it can index the object, like obj[key]
. The main issue is that, in some cases, an object can have other enumerable properties than those expressed in its type so in practice it could not be true that every key given by Object.keys()
is of type keyof T
; however, if you are sure that the object does not have other properties, like in the example where obj
is created from an object literal, then the assertion is safe, but you need to express that explicitly.