Marcus Krahl
Marcus Krahl

Reputation: 684

Interface cannot be added to object literal

I am trying to add an interface to an object literal in TypeScript 1.8.10, but it does not seem to work:

interface TestInterface {
    value: string 
}

let references = {
    interfaceReference: TestInterface
}

If I compile the code, the compiler throws the error Cannot find name "TestInterface" although it is correctly specified just before. I need to add the interface to an object as part of an Angular 2 project.

If I replace the interface with an abstract class everything seems to work:

abstract class TestInterface {
    value: string 
}

let references = {
    interfaceReference: TestInterface
}

However being able to use interfaces in these definitions would result in cleaner code. So, I hope there is a way to do this.

EDIT: To clarify what I want to do and why I am using interfaces: Angular 2 includes a dependency injection mechanism. You can specify the mapping from abstract service definitions to concrete service implementations in an object literal in the bootstrap code:

bootstrap(AppComponent, [ { provide: TestInterface, useClass: TestClass} ]

However this does not work if TypeScript cannot set the value of an object property to an interface

Upvotes: 1

Views: 293

Answers (3)

James Monger
James Monger

Reputation: 10665

You're trying to set the value of interfaceReference to TestInterface, which doesn't exist in the runtime (as interfaces are not compiled down to JavaScript).

You should instead use a colon (:) to set the type of references, and then you can set your value.

interface TestInterface {
    value: string 
}

let references: {
    interfaceReference: TestInterface
};

references.interfaceReference = {
    value: "some value"
};

Upvotes: 1

Maximilian Riegler
Maximilian Riegler

Reputation: 23506

The reason for tsc complaining is, that interfaces don't get transpiled to JavaScript, but classes do.

So what you're doing in your code is assigning a JavaScript object to the variable references. The value after the : must be an expression with a value (a variable for instance), which works, if TestInterface is a class, because it gets transpiled as a variable like this:

var TestInterface = (function () {
    function TestInterface() {
    }
    return TestInterface;
}());

To make your assignment actually work you have to rewrite it to something like this:

let references: { interfaceReference: TestInterface } = { interfaceReference: null };

On the other hand, if you're keen about using interfaces, why start using JavaScript objects? A better way would be to encapsulate those references again like this:

interface TestInterface {
    value: string 
}

class InterfaceReferences {
    constructor(public interfaceReference: TestInterface) {}
}

let references: InterfaceReferences = new InterfaceReferences(testInterface);

Upvotes: 2

Radim Köhler
Radim Köhler

Reputation: 123861

This is the way how to define type:

interface TestInterface {
    value: string 
}

// firstly define type of the variable - next assign it value
let references: { 
    interfaceReference: TestInterface
} = {
    interfaceReference: null,
};

so, firstly - after the ":" we define the type
and secondly - after the "=" we define its value

even better would be to create an interface:

interface SomeType { 
    interfaceReference: TestInterface
}

let references: SomeType = {
    interfaceReference: null,
};

because we could reuse that SomeType later

Upvotes: 1

Related Questions