Reputation: 7212
function last(anArray:any[]) /*:????*/ {
return anArray[anArray.length-1];
}
Without resorting to generics, is it possible to specify the return type in the function above being the type of the elements of the argument so
let strs:string[]=["aaa","bbb","ccc"];
let lastStr=last(strs); // type of lastStr should be string
let dates:Date[]=[new Date];
let lastDate=last(dates); // type of lastDate should be Date
Edit: Seeing the fine answer from @Titian Cernicova-Dragomir I should have stated "Without resorting to generics when invoking the function"
Upvotes: 0
Views: 743
Reputation: 26398
You can't avoid the generics, but you don't have to specify them as they can be inferred automatically. The accepted answer is probably good enough for your needs, but there is another way...
Typescript 2.8 will introduce type inferring (its currently published as a nightly build). With it you can support (fixed-size N) tuples of arbitrary types, rather than all elements being the same type, by combining conditional-types with type-inference.
type tuple =
[any] |
[any, any] |
[any, any, any] |
[any, any, any, any];
type TupleLast<T extends tuple> =
T extends [infer L] ? L :
T extends [any, infer L] ? L :
T extends [any, any, infer L] ? L :
T extends [any, any, any, infer L] ? L : any;
function last<T extends tuple>(arg: T): TupleLast<T> {
return arg[arg.length - 1];
}
Consider this answer a mental exercise of what can be done - I'm still messing with the new toys. :D
Upvotes: 2
Reputation: 249506
Not sure why you say 'without resorting to generics'. This is exactly the reason for generics in typescript. Using generics is not that hard:
function last<T>(anArray:T[]) :T {
return anArray[anArray.length-1];
}
// usage
let strs:string[]=["aaa","bbb","ccc"];
let lastStr=last(strs); // string
let dates:Date[]=[new Date()];
let lastDate=last(dates); //date
Without generics there is no way to accomplish this.
Upvotes: 1