Skip to content

Bloomberg feedback for 4.9 Beta #51042

@dragomirtitian

Description

@dragomirtitian

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:

  1. Some methods in classes have moved in the JS output. 4.9 respects original order so this seems intentional. Sample
  2. Some declaration maps have changed.
  3. Some property aliases in destructuring have been removed from declarations. (Seems like a good change and a continuation of work in 4.8)
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DiscussionIssues which may not have code impact

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions