Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I don't understand why this code generates a TypeScript error. (It's not the original code and is a bit derived, so please ignore the non-sense in the example):

interface Images {
  [key:string]: string;
function getMainImageUrl(images: Images): string {
  return images.main;

I'm getting this error (using TypeScript 1.7.5):

error TS2339: Property 'main' does not exist on type 'Images'.

Of course I could get rid of the error by writing:

return images["main"];

I'd prefer to not use string to access the property. What can I do?

@basarat what are these definitions good for when TS compiler doesn't use it the way one would expect? – hgoebl Jul 12, 2016 at 16:30 <ng-container class="varience" *ngIf ="vari; else second" > <h1>{{display_vari_price}}</h1> <ng-template #second> <ng-container> <h4 id="rate"> Price : {{ slide.price }}</h4> <h3> Offer Price :{{slide.saleprice}}</h3></ng-container> </ng-template> </ng-container> property second does not exist on this component – raghu raman Apr 29, 2021 at 5:44

If you want to be able to access images.main then you must define it explicitly:

interface Images {
    main: string;
    [key:string]: string;
function getMainImageUrl(images: Images): string {
    return images.main;

You can not access indexed properties using the dot notation because typescript has no way of knowing whether or not the object has that property.
However, when you specifically define a property then the compiler knows that it's there (or not), whether it's optional or not and what's the type.

You can have a helper class for map instances, something like:

class Map<T> {
    private items: { [key: string]: T };
    public constructor() {
        this.items = Object.create(null);
    public set(key: string, value: T): void {
        this.items[key] = value;
    public get(key: string): T {
        return this.items[key];
    public remove(key: string): T {
        let value = this.get(key);
        delete this.items[key];
        return value;
function getMainImageUrl(images: Map<string>): string {
    return images.get("main");

I have something like that implemented, and I find it very useful.

First of all: it's a helpful answer and might be a solution for my problem. But then: what is the sense of declaring "map-like" objects with [key: string]: aType? – hgoebl Jul 12, 2016 at 9:54

The correct fix is to add the property in the type definition as explained in @Nitzan Tomer's answer. If that's not an option though:

(Hacky) Workaround 1

You can assign the object to a constant of type any, then call the 'non-existing' property.

const newObj: any = oldObj;
return newObj.someProperty;

You can also cast it as any:

return (oldObj as any).someProperty;

This fails to provide any type safety though, which is the point of TypeScript.

Workaround 2

Another thing you may consider, if you're unable to modify the original type, is extending the type like so:

interface NewType extends OldType {
  someProperty: string;

Now you can cast your variable as this NewType instead of any. Still not ideal but less permissive than any, giving you more type safety.

return (oldObj as NewType).someProperty;
                <ng-container class="varience" *ngIf ="vari; else second" > <h1>{{display_vari_price}}</h1> <ng-template #second> <ng-container> <h4 id="rate"> Price : {{ slide.price }}</h4> <h3> Offer Price :{{slide.saleprice}}</h3></ng-container> </ng-template> </ng-container> property second does not exist on this component
– raghu raman
                Apr 29, 2021 at 5:44

I'm no expert in Typescript, but I think the main problem is the way of accessing data. Seeing how you described your Images interface, you can define any key as a String.

When accessing a property, the "dot" syntax (images.main) supposes, I think, that it already exists. I had such problems without Typescript, in "vanilla" Javascript, where I tried to access data as:

return json.property[0].index

where index was a variable. But it interpreted index, resulting in a:

cannot find property "index" of json.property[0]

And I had to find a workaround using your syntax:

return json.property[0][index]

It may be your only option there. But, once again, I'm no Typescript expert, if anyone knows a better solution / explaination about what happens, feel free to correct me.

You are asking what can you do / why do you have the error. I'm trying to explain you why do you have this error, and what could be your options considering my personnal knowledge. As told, anyone could have a better answer, I'm trying to help. The non-definition of a main property in your Images interface is definitely your problem there. – Yassine Badache Jul 12, 2016 at 9:58 No, it's not the problem. The property "main" exists. It's not a runtime-problem, but compile-time. And I'm not accessing the property through a variable, but "main" is really the name of the property. – hgoebl Jul 12, 2016 at 10:00 I was getting the error TS2339 on req.header.mod_api_key = 'somevalue' but req.header['mod_api_key'] = 'somevalue' did not give me the error. const a='mod_api_key'; req.header[a] also worked. – Brian C. Mar 7, 2017 at 20:32

Starting with TypeScript 2.2 using dot notation to access indexed properties is allowed. You won't get error TS2339 on your example.

See Dotted property for types with string index signatures in TypeScript 2.2 release note.

Supposedly less hacky solution:

if ("property" in obj) {
  console.log(`Can access ${obj.property}`)

The correct fix is to add the property in the type definition as explained by @Nitzan Tomer. But also you can just define property as any, if you want to write code almost as in JavaScript:

arr.filter((item:any) => {
    return item.isSelected == true;
                <ng-container class="varience" *ngIf ="vari; else second" > <h1>{{display_vari_price}}</h1> <ng-template #second> <ng-container> <h4 id="rate"> Price : {{ slide.price }}</h4> <h3> Offer Price :{{slide.saleprice}}</h3></ng-container> </ng-template> </ng-container> property second does not exist on this component
– raghu raman
                Apr 29, 2021 at 5:44

I was getting this error on Vue 3. It was because defineComponent must be imported like this:

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
    name: "HelloWorld",
    props: {
        msg: String,
    created() {
        this.testF();
    methods: {
        testF() {
            console.log("testF");
</script>
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

Why does the react 18.2 tutorial throws TS2339 Property 'X' does not exist on type 'Readonly<{}>' See more linked questions