You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需非空断言或可选标记,消除Deferred类TS编译警告可行吗?

问题:如何消除TypeScript中Deferred类的初始化警告(不使用非空断言或可选属性)

定义如下Deferred<R>类:

export class Deferred<R> {
  promise: Promise<R>;
  resolve: (value: R | PromiseLike<R>) => void;
  reject: (error?: any) => void;

  constructor() {
    this.promise = new Promise((res, rej) => {
      this.resolve = res;
      this.reject = rej;
    });
  }
}

由于Promise的执行器是同步执行的,resolve和reject属性会在构造函数完成前被赋值,并非可选属性,但TypeScript编译器仍会警告这两个属性未在构造函数中直接初始化。需要在不使用非空断言!、不将属性标记为可选的前提下消除警告。


解决方案

方法1:先赋值临时符合类型的函数

在构造函数中先给resolve和reject赋值一个临时的、符合类型定义的函数(比如抛出错误的函数),后续Promise执行器会同步覆盖这些值,既满足TypeScript的类型检查,也不会影响运行时逻辑:

export class Deferred<R> {
  promise: Promise<R>;
  resolve: (value: R | PromiseLike<R>) => void;
  reject: (error?: any) => void;

  constructor() {
    // 临时赋值满足类型检查,实际会被Promise执行器同步覆盖
    this.resolve = () => { throw new Error("Deferred resolve未初始化"); };
    this.reject = () => { throw new Error("Deferred reject未初始化"); };
    
    this.promise = new Promise((res, rej) => {
      this.resolve = res;
      this.reject = rej;
    });
  }
}

方法2:构造函数内临时变量中转

通过构造函数内部的临时变量接收Promise的resolve/reject,再赋值给实例属性。这里临时变量的非空断言仅作用于内部,不会污染类的属性定义:

export class Deferred<R> {
  promise: Promise<R>;
  resolve: (value: R | PromiseLike<R>) => void;
  reject: (error?: any) => void;

  constructor() {
    let resolve: typeof this.resolve;
    let reject: typeof this.reject;
    this.promise = new Promise((res, rej) => {
      resolve = res;
      reject = rej;
    });
    // 由于Promise执行器同步执行,此处resolve/reject必然已赋值
    this.resolve = resolve!;
    this.reject = reject!;
  }
}

内容的提问来源于stack exchange,提问作者Matthieu Riegler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 08:38:49