You've already learned how to work with dates and times in JavaScript. When we want to interact with temporal data in TypeScript, it doesn't bring any additional functionality that is not present in JavaScript. It also allows for better type safety and autocompletion when working with dates, thanks to its static typing. Let's take a look at how TypeScript facilitates working with dates.
The Date type
The Date type in TypeScript is simply a representation of built-in Date objects also accessible in JavaScript. When working with Date types in TypeScript, you can achieve type safety just by declaring the type of these date objects using type annotation:
let myDate: Date = new Date();
console.log(myDate); // [LOG]: Date: "2023-09-20T13:57:13.399Z"
The above code initializes a Date object representing the current date and time, and then prints it. Here, since we annotated myDate's type as Date, we just tell TypeScript that our variable myDate has to be a Date object. This means that if we try to assign a non-date value to this variable, the TypeScript compiler will throw an error:
myDate = "2023-09-20"; // Error: Type 'string' is not assignable to type 'Date'.
In this example, when we attempt to reassign myDate with a string value, we will get a compile-time error. It is because, in the previous code block, the type of myDate was specified as Date, and here, TypeScript identifies that "2023-09-20" is a string, not a date object.
Using Date for function parameters and return types
TypeScript also allows you to specify the types of function parameters and return types. When you have a function that is expected to take Date as a parameter or your function is expected to return a Date, TypeScript can catch these at compile time if you try to pass something that's not a Date.
function addOneDay(dateArg: Date): Date {
let result = new Date(dateArg.getTime() + 24 * 60 * 60 * 1000);
return result;
}
let today = new Date();
let tomorrow = addOneDay(today);
console.log(tomorrow);
Here, the code above defines a function called addOneDay, which accepts dateArg as input and returns the date for the next day. The function is then used to calculate tomorrow's date based on the current date, and the result is logged. You'll also see that inside the argument parentheses, it specifies that the dateArg parameter should have the type of Date as (dateArg: Date). In the same line after the colon, the return type of the function is specified as : Date. In this case, the function is also expected to return a Date object.
Now let's try to pass a string instead of a date:
let dateImpostor = "I'm not a date, but I'm still a string attached!";
let theDayAfter = addOneDay(dateImpostor); // TypeScript will throw an error at compile time
If we try to pass a string to addOneDay instead of a Date, TypeScript will catch this error at compile time.
Defining Date types with interfaces
In this section, you'll come across a TypeScript type that we'll delve into further in a later topic, Interfaces. For now, to keep this simple, interfaces in TypeScript are a way to define custom types for objects. They are primarily used to shape object properties and methods. They specify a list of properties and methods that a class or object should have. To implement them in classes, you can use the extends keyword and extend interfaces.
The MyDateObject interface in the following code sample specifies the structure for objects with two properties: sampleDate of type Date and locale of type string. The sampleDate denotes a particular date in time, whereas the locale is a string that identifies the locale code. Because the following myDateObject variable is of type MyDateObject, it must follow the structure set by the interface. That's why it has two properties, each with a date and a string value.
interface MyDateInterface {
sampleDate: Date;
locale: string;
}
let myDateObject: MyDateInterface = {
sampleDate: new Date(),
dateFormat: "en-US"
};
In this example, we use Date as the type definition within the interface, telling TypeScript that the sampleDate property of the MyDateInterface interface must be a date object. TypeScript enforces this at compile time, helping to prevent errors and ensuring that objects have the correct structure.
Conclusion
In this topic, you learned how to interact with the Date type in TypeScript and how TypeScript makes working with dates more straightforward and efficient. The Date type in TypeScript allows you to clearly declare date variables, preventing type errors. It also helps in maintaining data consistency through interfaces, making date-related coding tasks more convenient.