-1

Coming from Java, it is well understood that an interface is a contract and thus has only method signatures and constants. Trying to learn Typescript, I am surprised to see data variables in the interface definition see Microsoft article.

It is hard to understand why. Then what is the difference between a class and interface with only data variables in each.

Having a data variable in a language means storage will be allocated.

Why should an interface have data variables. Shouldn't it be allowed only for classes?

interface ICustomerShort
{
  Id: number;
  FullName: string;
}
likejudo
  • 3,396
  • 6
  • 52
  • 107
  • In short, interfaces in TypeScript do not only assert the presence of methods, but of attributes aswell. Remember that TypeScript is a superset of JavaScript, and in JavaScript, one can access any attribute on an object, but it may not exist and the access results in an `undefined`. – Turing85 Jan 25 '20 at 16:58
  • @Turing85 I do not understand your comment. Why should an interface have data variables. Shouldn't it be allowed only for classes? – likejudo Jan 25 '20 at 17:04
  • ... let me formulate a fully fledged answer... – Turing85 Jan 25 '20 at 17:06
  • Does this answer your question? [Typescript abstract property](https://stackoverflow.com/questions/59722411/typescript-abstract-property) – kaya3 Jan 25 '20 at 17:33
  • I think the TL;DR; of kaya3's link is that interfaces in both language define the "what" but not the "how". In Java it's typical to have getters for private properties but that is generally not idiomatic JavaScript. So where your Java interface would have `String getName()`, TypeScript would have `name: string`. Those properties can be implemented using transparent getters under the hood as well, if needed. – Max Jan 25 '20 at 17:53
  • @kaya3 If they are data variables, then it is my understanding they would have storage as well. So how can they be abstract? – likejudo Jan 25 '20 at 17:55
  • @kaya3 why are you closing my question? – likejudo Jan 25 '20 at 17:58
  • @likejudo I closed it as a duplicate of the linked question, which it is. The close reason at the top of the post shows only the reason selected by the first user who voted to close, not everyone voted to close with the same reason. – kaya3 Jan 25 '20 at 17:59
  • @likejudo An abstract property declaration does not allocate space for the property's value, in the same way that an abstract method declaration cannot actually be invoked. An abstract property declaration must be implemented by the implementing class declaring a property conforming to the abstract property's declaration, in the same way that an abstract method declaration must be implemented by the implemented class declaring a method conforming to the abstract method's declaration. – kaya3 Jan 25 '20 at 18:03
  • @kaya3 don't be in such a hurry to close questions. I don't think it is a duplicate. In your linked answer you have not given any reference where it says a data variable defined in an interface does not allocate space for the properties value. – likejudo Jan 25 '20 at 18:09
  • @likejudo But your question doesn't ask anything about allocating space for them. If that is what you intended to ask about, you can edit your question and I will vote to reopen it. – kaya3 Jan 25 '20 at 18:11

1 Answers1

1

The simple answer is: Because Java and TypeScript are different languages, thus they can behave differently. However, I myself like to understand why language constructs are how they are. So, let's take a dive!

To start of, we need to know that TypeScript is a superset of JavaScript. In essence, every valid JavaScript program is also a valid TypeScript program. In fact, TypeScript gets transpiled to JavaScript, so in the end, everything is JavaScript. What TypeScript does provide, however, is compile-time type checking.

Next point to notice is that both JavaScript and TypeScript are duck-typed languages. The duck-typing is, however, in both instances, different. Let us first look at a JavaScript example:

var person = {
    name: 'John Doe'
};
console.log(person.age);

In the code above, the property of age of person is accessed. But this property does not exist. For this, JavaScript has the undefined value and this is what is returned. This is an example of the extremely typing in JavaScript.

Now TypeScript gives additional type-checking, making it more Java-like with respect to typing. Let's consider the following TypeScript code:

interface Person {
    name: string
    age: number
}

function printPerson(person: Person) {
    console.log(person);
}

class PersonClass {
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
}

const personObject = new PersonClass('Jane Doe', 23);
printPerson(personObject);

const person = {
    name: 'John Doe',
    age: 42
};
printPerson(person);

const notAPerson = {
    name: 'Oops'
}
printPerson(notAPerson);

Playground example

First, there is an interface Person defined. It also enforces that only object having a string-attribute name and number-attribute age are considered to be Persons.

Next, we define a method to print Persons.

Then, we define a class PersonObject with a name- and an age-attribute. Notice that we do not reference the Person-interface in the PersonObject-class.

Now when we instantiate a PersonObject, we can pass is to the printPerson(...)-class since every PersonObject conforms to the Person-interface and gets converted.

We can do the same with inline-declared objects (const person = { name: 'John Doe', age: 42 };): it also conforms to the interface and thus can be passed to printPerson(...).

Finally, we have an inline-object having a name, but no age (const notAPerson = { name: 'Oops' }) and thus does not satisfy the Person-interface. The transpiler will complain. Notice, however, that the transpiler may still produce JavaScript code (depending on the transpiler settings) and the produced JavaScript code will execute the "faulty" call since there is no possibility in JavaScript to prevent the call.


Edit:

Thanks to @kaya3 who pointed out the following to me.

TypeScript's typing system is based on structural typing. It is based on compile-time type checking, not run-time type checking (which is how duck typing does it).

Turing85
  • 18,217
  • 7
  • 33
  • 58