Complementing the another answer, it is worth mentioning that in the end, the Typescript code is transposed into Javascript, which can help explain why it is not possible to do the Overload with Arrow functions.
If we use your code:
function parseToDate<T extends string | null>(date: T): T extends string ? Date : null;
function parseToDate(date: string | null): Date | null {
return typeof date === 'string' ? new Date(date) : null;
}
To test I used the Deno, for with him you can easily get the Javascript file generated from Typescript. In the case of the above code, the generated Javascript was:
"use strict";
function parseToDate(date) {
return typeof date === 'string' ? new Date(date) : null;
}
That is, a single function.
But I could also do so:
// só recebe uma string ou null
function parseToDate < T extends string | null > (date: T): T extends string ? Date : null;
function parseToDate(date: string | null): Date | null;
// recebe 3 números
function parseToDate(date: number, month: number, year: number): Date | null;
// implementação: ver mais em /a/418160/112052
function parseToDate(date: any, month?: any, year?: any): Date | null {
if (typeof date === 'string')
return new Date(date);
if (typeof date === 'number' && typeof month === 'number' && typeof year === 'number')
return new Date(year, month - 1, date);
return null;
}
That the resulting Javascript would remain a single function:
function parseToDate(date, month, year) {
if (typeof date === 'string')
return new Date(date);
if (typeof date === 'number' && typeof month === 'number' && typeof year === 'number')
return new Date(year, month - 1, date);
return null;
}
That is, all the overloads become a single function, as already explained in detail here.
And why with Arrow Function can’t?
With Arrow functions, you are actually creating a variable and assigning a function as its value. That is, if you do something like:
let func = (x: number): number => x + 1;
func = (x: number): number => x - 1;
// func contém somente a última arrow function
console.log(func(11)); // 10
In fact you are overwriting the value of the variable func
with another value (with another function). The first function created is "lost", and in the end you only have the last one. The resulting Javascript is:
let func = (x) => x + 1;
func = (x) => x - 1;
console.log(func(11));
Notice that I had to put the function body and the "arrow" (=> x + 1
and => x - 1
), because without it the code does not compile. That is, your example was incomplete.
And in your code, you used const
, then gave error because it was trying to create the same variable twice.
But here’s the thing, I couldn’t do that:
let func = (x: number): number => x + 1;
// agora tem 2 parâmetros
func = (x: number, y:number): number => x + y;
This makes a mistake:
error: TS2322 [ERROR]: Type '(x: number, y: number) => number' is not assignable to type '(x: number) => number'.
func = (x: number, y:number): number => x + y;
Because initially the variable is of the type "function that receives a number
and returns a number
", but I tried to put in it a "function that gets two number
's and returns a number
", and as they are incompatible types, gives the error.
That is, once a variable has a value of Arrow Function, you could not set it with another function with different signature (which would also prevent the Overload - but even if that were possible, it wouldn’t actually be a Overload, because as I said, you would only be overwriting the value of the variable).
In that case, a way to have a Arrow Function accepting several parameters of different types (similar to a function
overloaded) would declare the parameters in the most generic way possible, within the options you want to consider:
let parseToDate2 = (date: string | number | null, month?: number, year?: number): Date | null => {
if (typeof date === 'string')
return new Date(date);
if (typeof date === 'number' && typeof month === 'number' && typeof year === 'number')
return new Date(year, month - 1, date);
return null;
};
Which turns into the following Javascript:
let parseToDate2 = (date, month, year) => {
if (typeof date === 'string')
return new Date(date);
if (typeof date === 'number' && typeof month === 'number' && typeof year === 'number')
return new Date(year, month - 1, date);
return null;
};
That is, it becomes basically the same function resulting from the Overload when we use function
(considering, of course, the differences between function
and Arrow Function).
But I’d still prefer to use the first option (function
), or the suggestions of another answer.
Then it’s not because of
const
, which does not allow creating another variable with the same name?– hkotsubo
@hkotsubo is, it seems to be that same . I did some tests with
var
,let
andconst
and saw the MDN documentation, it makes sense. There is a different "notation" that allows the overload in Arrow functions? I found some answers on Soen but I could not adapt to the example of my question– Rafael Tavares