WillyC WillyC - 2 months ago 11
TypeScript Question

Dates in a Typescript interface are actually strings when inspected

Unfortunately the total code to reproduce this would be extensive, so I'm hoping that my problem is obvious with what I can easily provide. If required, I'll post a more complete solution.

First, I am defining an interface:

export interface ITest {
myDate: Date;
}


Then I create an array of these for testing:

export const TEST: ITest[]=[{myDate: new Date(1995, 8, 1)}]


I expose these using a service in Angular2 that is hitting the InMemoryDbService from
angular2-in-memory-web-api
. The code where I call this and get the array is as follows:

get(): Promise<ITest[]>{
return this.http.get(this.testUrl)
.toPromise()
.then(response => response.json().data as ITest[])
.catch(this.handleError);
}


...and then I bring it into my component with:

this.testService.get().then(tests => {
this.tests = tests;
console.log("Date Type:"+typeof(this.tests[0].myDate));
});


This all works fine, but the problem is the
console.log
statement shown there results in:

Date Type:string


The data in it is correct, in that the string held by my date is
1995-09-01T07:00:00.000Z
, but the main issue is - it isn't a
Date
it is a
string
! In VS Code I even get code completion for methods like
toDateString
but when I execute them I (of course) get
toDateString is not a function
.

I am pretty sure that the issue is occurring with
response => response.json().data as ITest[]
, but why isn't the date data being cast to an actual
Date
? I'm doing it wrong, that I understand. How should I be handling this such that I can have my objects obtain the types I expect?

Answer

You are using an interface and type assertion to basically tell TypeScript that the object conforms to that interface.

But this is not actually the case as what you are casting is a json object in which the "myDate" property is being represented as a string.

Using type-assertion does not affect generated javascript code in any way - you have to do the actual type conversion yourself.

The reason why it comes as string is that there is no type defined in JSON format to represent Date, so the server in all likelihood is just sending a result of date.toString().

One option for you would be to have a class for representing the returned value and instantiate an object from the JSON properties like so:

var response = JSON.parse(JSON.stringify({ myDate: new Date() }));

class Test  {
    constructor(json: { myDate: string }) {

        this.myDate = new Date(json.myDate);
    }

    myDate: Date;
}

let test = new Test(response);
console.log("Type: " + typeof (test.myDate));
console.log("Value: " + test.myDate);