Reputation: 4931
const isObjectClass = (value: any, className: any) => (Object.prototype.toString.call(value) === `[object ${className}]`);
export const isDate = (value: any) => isObjectClass(value, 'Date');
const time = (time: Date): string => {
return ((isDate(time) && !isNaN(time)) ? time : new Date()).toISOString();
};
In the above function time
, I am checking if the input is a valid Date object or not. If valid, it will return the string version of passed Date. If invalid, it will return the string version of the current date.
The problem with isDate()
is, it will return true for input values new Date()
and new Date(undefined))
. To avoid this I used !isNaN()
which return false in case of !isNaN( new Date(undefined) )
.
Now the problem is typescript is not allowing me to pass Date
object to isNaN
function.
error
TS2345: Argument of type 'Date' is not assignable to parameter of type 'number'.
Any suggestions?
Upvotes: 8
Views: 4238
Reputation: 606
Fixing this by adding a call to getTime() is valid. But I'd point out that your code is already correct as-is, and doesn't need runtime behavior changes to appease Typescript. If you'd like to fix the type-checking without a runtime impact, here are two "pure typescript annotation" fixes.
Why your code isn't wrong
As of this writing, the type library lib.es5.d.ts
defines isNaN's parameter as strictly a number, with no other options:
declare function isNaN(number: number): boolean;
...however the specification for isNaN
says:
Returns true if the argument coerces to NaN. If ToNumber(number) is NaN, return true.
...so it's correct to pass any type of parameter that can be coerced to a number, it doesn't have to already be a number. The type declaration doesn't model this conversion behavior, even though a Date will indeed coerce to a number. Here are two ways to fix this purely with type annotation:
Option A: Re-declare isNaN()
Since you know that isNaN is more capable and permissive than Typescript declares, you can add your own more permissive declaration to the top of your code. This will override the built-in one in scope, and then your code will typecheck:
declare function isNaN(arg: number|Date): boolean;
Option B: Coercion
For a spot-fix only at this one call site, you can coerce the type of the argument through unknown
and then to number
, like so:
const time = (time: Date): string => {
return ((isDate(time) && !isNaN(time as unknown as number)) ? time : new Date()).toISOString();
};
...this is a little less correct because it's not technically true that time
is a number, but it will silence the error. Either of these changes will affect only how tsc checks your code, but will not change the generated Javascript.
Upvotes: 3
Reputation: 212
You can convert this date object to time (!isNaN(time.getTime())
) like as follows,
const time = (time: Date): string => {
return ((isDate(time) && !isNaN(time.getTime())) ? time : new Date()).toISOString();
};
In here getTime method returns numeric value of the respective date object. So you can easily use this numeric value with isNaN
Upvotes: 6
Reputation: 258
That's maybe because you want to pass a number in your function time(), number can't be cast as Date.
isObjectClass and isDate are a bit useless, time already check the type of the argument.
Upvotes: -2