Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error TS2339: Property 'x' does not exist on type 'Y'

Tags:

typescript

I don't understand why this code generates 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 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 when writing:

return images["main"]; 

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

like image 669
hgoebl Avatar asked Jul 12 '16 09:07

hgoebl


People also ask

How do I fix TS2339 error?

To fix the error "TS2339: Property 'x' does not exist on type 'Y'" with TypeScript, we should make sure the properties are listed in the interface that's set as the type of the object. interface Images { main: string; [key: string]: string; } const getMainImageUrl = (images: Images): string => { return images. main; };

How do you fix property does not exist on type?

The "Property does not exist on type '{}'" error occurs when we try to access or set a property that is not contained in the object's type. To solve the error, type the object properties explicitly or use a type with variable key names.

Does not exist on type string?

The "Property does not exist on type String" error occurs when we try to access a property that does not exist on the string type. To solve the error, use an object instead of a string, or make sure you're accessing a valid built-in method on the string.

Does not exist on type void?

The "Property does not exist on type void" error occurs when we try to access a property on the return value of a function that doesn't return anything. To solve the error, make sure to return the correct value from all of the function's code paths.


2 Answers

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.


Edit

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.

like image 172
Nitzan Tomer Avatar answered Sep 20 '22 21:09

Nitzan Tomer


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.


(Hacky) 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; 
like image 39
Nelu Avatar answered Sep 17 '22 21:09

Nelu