Let's assume we have the following TypeScript code:
namespace Utils.Date {
export fromInternal = (dateString: string): Date => {
const year = parseInt(dateString.substr(0, 4), 10);
const month = parseInt(dateString.substr(4, 2), 10) - 1;
const day = parseInt(dateString.substr(6, 2), 10);
return new Date(year, month, day); // error TS2351
}
}
This causes error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature
, because the namespace Utils.Date
now conceals the built-in Date constructor.
I know I can can use window.Date
to access the Date constructor in the browser, but when I try to do that in TypeScript I get error TS2339: Property 'Date' does not exist on type 'Window'
. Instead I would have to use something like window['Date']
, but then I'd lose the type safety.
Is there a way to access the Date constructor without changing the namespace and still being typesafe? Or is it simply bad practice to conceal global objects? Even then I'm curious to know if there would be a way.
My preferred solution is to avoid the name clash, especially where your code is so closely related to the clashed name. The name clash will eventually affect more and moer things that you add to the Utils
namespace.
namespace Utils.DateParsers {
But you could shim the Date
object into an intermediate variable if you are determined to keep the name clash.
const outerDate = Date;
namespace Utils.Date {
const fromInternal = (dateString: string): Date => {
const year = parseInt(dateString.substr(0, 4), 10);
const month = parseInt(dateString.substr(4, 2), 10) - 1;
const day = parseInt(dateString.substr(6, 2), 10);
return new outerDate(year, month, day); // error TS2351
}
}