Reputation: 44376
The following does not compile:
function f(n: number): (number|null) {
return n > 0 ? n : null;
}
function g(a: number[]): number[] {
return a.map(f).filter(n => n);
}
The problem is, the compiler does not understand the semantics of filter(), and does not realize that it will omit all falsey entries in the list. As a result, it fails with "Type '(number | null)[]' is not assignable to type 'number[]'."
The following does work:
function g(n: number[]): number[] {
return n.map(f).filter(n => n).map(n => n!);
}
but goes through a meaningless loop. This works too
function g(a: number[]): number[] {
return a.map(f).filter(n => n) as number[];
}
but a cast like that will obscure a multitude of sins. Any other suggestions?
Upvotes: 2
Views: 1097
Reputation: 1584
You can extract the filtering method out and use Type Guards to make it a little more precise.
Like so:
function f(n: number): (number | null) {
return n > 0 ? n : null
}
function hasValue(n: number | null): n is number {
return !!n
}
function g(a: number[]): number[] {
return a.map(f).filter(hasValue)
}
Note. !!n will filter out 0 as well so not strictly correct but suitable for highlighting type guards
Upvotes: 4