-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
We are in the process of evaluating the impact of upgrading to 4.9 on our codebase. Here are some preliminary findings.
This is shaping up to be a low impact release: just <1% of packages have new build errors with 4.9.
# | Change | Affects | Release notes | Packages affected |
---|---|---|---|---|
1 | Declare no longer appears on type in declaration files | Declaration Files | Not Announced | ~30% |
2 | NaN comparison | Type checking | Announced | <0.3% |
3 | In operator is more strict about RHS operand being object | Type checking | Announced | <0.5% |
4 | Intersection between type parameter and undefined | Type checking | Not Announced | <0.3% |
5 | Generic type parameter loses defined constraint | Type checking | Not Announced | <0.15% |
Declare no longer appears on type in declaration files
This is a benign change to declarations (the declare
keyword is no longer generated in d.ts files for type aliases). While this change does not cause issues, it did cause a lot of noise when trying to evaluate if there were meaningful declaration changes.
NaN
comparison
TypeScript now warns on comparison with NaN
. This causes two packages to break in what looks like missed bugs in code.
In operator is more strict about RHS operand being object
This caused several packages to break. Some errors seem to be good, such as requiring type parameters to extend object instead of being unconstrained.
We did find a related issue, reported as #51007 where x instanceof Object
does not narrow x to be an object.
export function isHTMLTable(table: unknown): boolean {
return !!table && table instanceof Object && 'html' in table;
}
Intersection between type parameter and undefined
Intersection between a type parameter and undefined no longer reduces to never.
type AB = "A" | "B"
function x<T_AB extends AB>() {
let r2: never = null! as T_AB & undefined
}
This seems like a bug, reported as #51041
Generic type parameter loses defined constraint
When we use a conditional type to test if a type parameter extends another type, the original constraint of the type parameter is lost:
export type TypeA = {
A: 'A',
B: 'B',
}
export type TypeB = {
A: 'A',
B: 'B',
C: 'C',
}
// Fails to index TypeA with T
type R<T extends keyof TypeA> =
T extends keyof TypeB ? [TypeA[T], TypeB[T]] : never
This seems like a bug, reported as #51009
Other changes
There were some other minor changes:
- Some methods in classes have moved in the JS output. 4.9 respects original order so this seems intentional. Sample
- Some declaration maps have changed.
- Some property aliases in destructuring have been removed from declarations. (Seems like a good change and a continuation of work in 4.8)
- One complex mapped and conditional type has lost its ability to be directly asserted as another complex mapped and conditional type. While this is a breaking change, the types are complex enough I would not have expected them to be assignable or assertable anyway.