type A = number | string
function isNumber(_): _ is number { return typeof _ === 'number' }
const as: A[] = [1, 2, '3']
// (1) - OK: bs is number[]
let bs = as.filter(isNumber)
// (2) - Not OK - cs is still A[], but should be number[]
let cs = as.filter(_ => isNumber(_))
// (3) - Not OK - ds is still A[], but should be string[]
let ds = as.filter(_ => !isNumber(_))
Similar issues: https://github.com/Microsoft/TypeScript/issues/7657, https://github.com/Microsoft/TypeScript/issues/5101, https://github.com/Microsoft/TypeScript/issues/5951
The request here is to infer user defined type guards from return expression of functions. i.e.:
function isNumber(a): a is number {
....
}
function myIsNumber(a) {
return isNumber(a); // should infer `a is number`
}
function isString(a: number | string) {
return !isNumber(a); // should infer `a is string`
}
I wish this issue got more attention because a bit of inference could go a long way.
I implemented a form of type predicate inference in 982c35fde3f3fe0a5a823456b27a45cb0618ce9c to get a feeling for the complexity. It goes beyond just propagating type predicates as outlined here and infers them as requested in #18572 and #19468. It's only a sketch and does not handle some common cases nor some of the edge cases I saw in other places that do type narrowing. That notwithstanding, I think the (implementation) complexity of an inference scheme for simple arrow types might be acceptable. However, I obviously lack the broader understanding necessary to properly assess this.
I want to emphasize how valuable an inference scheme like this could be. Manually specified predicates are not verified and thus error prone. The most common use case, as can be seen in #18572 and #19468, are filter
functions. Anybody who uses rxjs in combination with redux or some other library that encourages flux standard actions likely has Observable
s of such actions and filters them by type
. redux-observable has a dedicated function for this, which gives type safety at the cost of redundancy (both the type argument and the type
must be specified.
Once again, I wish this issue would get more attention. =)
Seems like a duplicate of https://github.com/Microsoft/TypeScript/issues/16069
Most helpful comment
The request here is to infer user defined type guards from return expression of functions. i.e.: