If you specify the type as indexable, then you must access the properties in this manner:
a["data"].bar
Your playground demo: adjusted to function correctly.
Learn more about Indexable Types.
Let's begin with the issue at hand:
interface Something {
name: string;
data: { [key: string]: any };
}
In your Something
interface, there is a specific property named name
of type string
, so the compiler understands what this signifies:
let a: Something = ...
console.log(a.name);
However, if I were to execute console.log(a["unknownKey"])
, how could the compiler ascertain the meaning of this unknownKey
? Is it a valid property within the object? What is its type?
Since you haven't specified that this object contains this key, the compiler cannot deduce, hence necessitating the usage of index notation.
How can we work around this?
One approach is to define the properties that are known to exist and used in your code. For instance, if you utilize the properties name
, id
, and address
, include them in your interface like so:
interface Something {
id: string;
name: string;
address: string;
data: { [key: string]: any };
}
Other properties can remain as indexes.
An alternative is to employ classes:
interface Something {
name: string;
data: { [key: string]: any };
}
class MySomething {
public name: string;
public else: string;
constructor(obj: Something) {
this.name = obj.name;
this.else = obj["else"];
}
}
Of course, utilizing any
is another option, bypassing the compiler's type checking:
let a: any = ...
console.log(a.myProperty);
This is not an ideal solution, but temporary implementation for resolving hurdles during migration to TypeScript until a better fit is determined to suit your requirements.