Separate Write Types on Properties

  • 允许getter的返回类型和setter的参数类型不一致
  • getter的返回类型G和setter的参数类型S,必须满足G extends S ```typescript // Class class Thing {

    size = 0;

    get size(): number {

    1. return this.#size;

    }

    set size(value: string | number | boolean) {

    1. let num = Number(value);
    2. // Don't allow NaN and stuff.
    3. if (!Number.isFinite(num)) {
    4. this.#size = 0;
    5. return;
    6. }
    7. this.#size = num;

    } }

// Object function makeThing(): Thing { let size = 0; return { get size(): number { return size; }, set size(value: string | number | boolean) { let num = Number(value);

  1. // Don't allow NaN and stuff.
  2. if (!Number.isFinite(num)) {
  3. size = 0;
  4. return;
  5. }
  6. size = num;
  7. }
  8. }

}

// Interface // Now valid! interface Thing { get size(): number set size(value: number | string | boolean); }

  1. ---
  2. <a name="Dkjdx"></a>
  3. # `override` and `--noImplicitOverride` Flag
  4. - `override`关键字:保证父类中必须有同名方法
  5. - `--noImplicitOverride` flag:禁用隐式覆盖父类方法,必须使用`override`关键字
  6. ```typescript
  7. class SpecializedComponent extends SomeComponent {
  8. override show() {
  9. // ...
  10. }
  11. override hide() {
  12. // ...
  13. }
  14. }

Template String Type Improvement

  • contextually typed:根据上下文类型环境推导类型

    1. function bar(s: string): `hello ${string}` {
    2. // Previously an error, now works!
    3. return `hello ${s}`;
    4. }
  • 更精准的template string类型推导 ```typescript declare let s: string; declare function f(x: T): T;

// Previously: string // Now : hello-${string} let x2 = f(hello ${s});

  1. - 不同template string类型兼容推导更精确
  2. ```typescript
  3. declare let s1: `${number}-${number}-${number}`;
  4. declare let s2: `1-2-3`;
  5. declare let s3: `${number}-2-3`;
  6. declare let s4: `1-${number}-3`;
  7. declare let s5: `1-2-${number}`;
  8. declare let s6: `${number}-2-${number}`;
  9. // Now *all of these* work!
  10. s1 = s2;
  11. s1 = s3;
  12. s1 = s4;
  13. s1 = s5;
  14. s1 = s6;

ECMAScript #private Class Elements

  1. class Foo {
  2. #someMethod() {
  3. //...
  4. }
  5. get #someValue() {
  6. return 100;
  7. }
  8. publicMethod() {
  9. // These work.
  10. // We can access private-named members inside this class.
  11. this.#someMethod();
  12. return this.#someValue;
  13. }
  14. }
  15. new Foo().#someMethod();
  16. // ~~~~~~~~~~~
  17. // error!
  18. // Property '#someMethod' is not accessible
  19. // outside class 'Foo' because it has a private identifier.
  20. new Foo().#someValue;
  21. // ~~~~~~~~~~
  22. // error!
  23. // Property '#someValue' is not accessible
  24. // outside class 'Foo' because it has a private identifier
  1. class Foo {
  2. static #someMethod() {
  3. // ...
  4. }
  5. }
  6. Foo.#someMethod();
  7. // ~~~~~~~~~~~
  8. // error!
  9. // Property '#someMethod' is not accessible
  10. // outside class 'Foo' because it has a private identifier.

ConstructorParameters Works on Abstract Classes

  1. abstract class C {
  2. constructor(a: string, b: number) {
  3. // ...
  4. }
  5. }
  6. // Has the type '[a: string, b: number]'.
  7. type CParams = ConstructorParameters<typeof C>;

Contextual Narrowing for Generics

  1. function makeUnique<T, C extends Set<T> | T[]>(collection: C, comparer: (x: T, y: T) => number): C {
  2. // Early bail-out if we have a Set.
  3. // We assume the elements are already unique.
  4. if (collection instanceof Set) {
  5. return collection;
  6. }
  7. // Sort the array, then remove consecutive duplicates.
  8. collection.sort(comparer);
  9. // ~~~~
  10. // error: Property 'sort' does not exist on type 'C'.
  11. for (let i = 0; i < collection.length; i++) {
  12. // ~~~~~~
  13. // error: Property 'length' does not exist on type 'C'.
  14. let j = i;
  15. while (j < collection.length && comparer(collection[i], collection[j + 1]) === 0) {
  16. // ~~~~~~
  17. // error: Property 'length' does not exist on type 'C'.
  18. // ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
  19. // error: Element implicitly has an 'any' type because expression of type 'number'
  20. // can't be used to index type 'Set<T> | T[]'.
  21. j++;
  22. }
  23. collection.splice(i + 1, j - i);
  24. // ~~~~~~
  25. // error: Property 'splice' does not exist on type 'C'.
  26. }
  27. return collection;
  28. }

Always-Truthy Promise Checks

  1. async function foo(): Promise<boolean> {
  2. return false;
  3. }
  4. async function bar(): Promise<string> {
  5. if (foo()) {
  6. // ~~~~~
  7. // Error!
  8. // This condition will always return true since
  9. // this 'Promise<boolean>' appears to always be defined.
  10. // Did you forget to use 'await'?
  11. return "true";
  12. }
  13. return "false";
  14. }

static Index Signatures

  1. class Foo {
  2. static hello = "hello";
  3. static world = 1234;
  4. static [propName: string]: string | number | undefined;
  5. }
  6. // Valid.
  7. Foo["whatever"] = 42;
  8. // Has type 'string | number | undefined'
  9. let x = Foo["something"];

.tsbuildinfo Size Improvements

--incremental builds


Lazier Calculations in --incremental and --watchCompilations


Import Statement Completions

image.png


Editor Support for @link Tags

  1. /**
  2. * To be called 70 to 80 days after {@link plantCarrot}.
  3. */
  4. function harvestCarrot(carrot: Carrot) {
  5. }
  6. /**
  7. * Call early in spring for best results. Added in v2.1.0.
  8. * @param seed Make sure it's a carrot seed!
  9. */
  10. function plantCarrot(seed: Seed) {
  11. // TODO: some gardening
  12. }

Go-to-Definition on Non-JavaScript File Paths


Breaking Changes

lib.d.ts Changes

删除:
Account, AssertionOptions, RTCStatsEventInit, MSGestureEvent, DeviceLightEvent, MSPointerEvent, ServiceWorkerMessageEvent, WebAuthentication

Errors on Always-Truthy Promise Check

--strictNullChecks

  1. declare var p: Promise<number>;
  2. if (p) {
  3. // ~
  4. // Error!
  5. // This condition will always return true since
  6. // this 'Promise<number>' appears to always be defined.
  7. //
  8. // Did you forget to use 'await'?
  9. }

Union Enums Cannot Be Compared to Arbitrary Numbers

  1. enum E {
  2. A = 0,
  3. B = 1,
  4. }
  5. function doSomething(x: E) {
  6. // Error! This condition will always return 'false' since the types 'E' and '-1' have no overlap.
  7. if (x === -1) {
  8. // ...
  9. }
  10. }

变通办法:

  1. enum E {
  2. A = 0,
  3. B = 1,
  4. }
  5. // Include -1 in the type, if we're really certain that -1 can come through.
  6. function doSomething(x: E | -1) {
  7. if (x === -1) {
  8. // ...
  9. }
  10. }
  1. enum E {
  2. A = 0,
  3. B = 1,
  4. }
  5. // Include -1 in the type, if we're really certain that -1 can come through.
  6. function doSomething(x: E | -1) {
  7. if (x === -1) {
  8. // ...
  9. }
  10. }
  1. enum E {
  2. // the leading + on 0 opts TypeScript out of inferring a union enum.
  3. A = +0,
  4. B = 1,
  5. }