TypeScript 4.8 has been officially released.

Changes since Beta and RC releases

Since the beta release, the stable version now supports excluding specific files from automatic import. The beta announcement made no mention of breaking changes around unused destructuring aliases in type signatures. Additionally, neither the Beta nor the RC release announcements describe API breaking changes in TypeScript syntax tree decorators. These are detailed in the new release announcement.

Major changes

Type narrowing enhancements for intersection types and union types

TypeScript 4.8 version pair --strictNullChecks Further enhancements have been made, mainly in the joint type and cross type, as well as the narrowed performance of the type.

For example, as the Top Type in the TypeScript type system, the unknown type includes all other types, in fact unknown and {} | null | undefined The effect is the same: the unique meaning of null, undefined types, plus the origin of all things {}.

infer extraction in template string type

In version 4.7, TypeScript supports the infer extends syntax, so that we can directly infer the value of the expected type in one step, without the need to judge the conditional statement again:

type FirstString<T> =
    T extends [infer S, ...unknown[]]
        ? S extends string ? S : never
        : never;
// 基于 infer extends
type FirstString<T> =
    T extends [infer S extends string, ...unknown[]]
        ? S
        : never;

Version 4.8 further enhances this. When infer is constrained to be a primitive type, it now deduces the type information of infer to the literal type level as much as possible:

// 此前为 number,现在为 '100'
type SomeNum = "100" extends `${infer U extends number}` ? U : never;
// 此前为 boolean,现在为 'true'
type SomeBool = "true" extends `${infer U extends boolean}` ? U : never;

At the same time, TypeScript will check whether the extracted value can be remapped back to the original string, as in SomeNum String(Number("100")) Is it equal to "100"in the following example, it can only be deduced to the number type because it cannot be remapped back:

// String(Number("1.0")) → "1",≠ "1.0"
type JustNumber = "1.0" extends `${infer T extends number}` ? T : never; 

Type deduction in bound types

Generic padding in TypeScript is also affected by its caller, as in the following example:

declare function chooseRandomly<T>(x: T,): T;
const res1 = chooseRandomly(["linbudu", 599, false]);

At this time, the type of res1 and the generic T of the function will be deduced as Array<string | number | boolean>but if we change the method:

declare function chooseRandomly<T>(x: T,): T;
const [a, b, c] = chooseRandomly(["linbudu", 599, false]);

At this time, a, b, and c are deduced as string, number, and boolean types, which means that the generic type of the function is filled as [string, number, boolean] Such a tuple type.

This way of populating generics is called Binding Pattern, and in version 4.8, type deduction based on binding pattern is disabled because its effect on generics is not always correct:

declare function f<T>(x?: T): T;
const [x, y, z] = f();

See the release announcement for details.

#TypeScript #officially #released #News Fast Delivery

Leave a Comment

Your email address will not be published. Required fields are marked *