无需非空断言或可选标记,消除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
相关产品推荐
相关产品推荐

