下面的代码段是否可以对readText
进行注释,以告诉编译器确保this.text
是string
而不是string | undefined
?
type MyResponse = {
text: () => Promise<string>;
};
class ResponseVerfier {
response: MyResponse;
text?: string;
constructor(response: MyResponse) {
this.response = response;
}
async readText() {
this.text = await this.response.text();
}
async verifyTextContains(value: string) {
await this.readText();
// I've run this.readText so I now know this.text is a string, not string | undefined
// However I'm currently getting an error "Object is possibly 'undefined'"
return this.text.includes(value);
}
}
答案 0 :(得分:0)
您可以使用non-null assertion postfix operator告诉编译器“在给定的表达式中,我的操作数不能为null或未定义”
所以,如果您写:
return this.text!.includes(value);
一切正常。这是您提供的保证。
答案 1 :(得分:0)
我认为TypeScript缺少使此代码正常工作所需的几个功能,以便运行时代码相同并且编译器验证其类型安全性。第一个缺少的功能是以某种方式完成user-defined type assertions (as suggested in this GitHub issue)的方式,类似于user-defined type guards的工作方式。这样,您可以告诉编译器this.readText()
将(最终)将this
的类型缩小为this & {text: string}
。即使具有该功能,您也需要能够返回类型声明的Promise
而不是类型声明本身,这将需要诸如propagation of type predicates (as suggested in this GitHub issue)之类的东西。如果这两个都实现了,那么也许您可以做类似的事情:
// DOES NOT COMPILE, DON'T TRY THIS
async readText(): Promise<this as (this & {text: string})> {
this.text = await this.response.text();
}
其中Promise<this as (this & {text: string})>
表示readText()
返回一个诺言,该诺言在解决后会将this
的类型缩小到其text
属性肯定是string
而不仅仅是string | undefined
。 las,这行不通。
使代码按原样工作而不在运行时进行任何更改的方法是使用类型断言,例如@Phillip的non-null assertion !
operator中所示的answer。
如果您不介意更改代码的工作方式,那么我强烈建议将异步和同步代码分成两个完全不同的结构,并让异步代码返回完全配置的同步对象,例如:
type MyResponse = {
text: () => Promise<string>;
};
// all async code should be in here
class AsyncResponseVerifier {
constructor(public response: MyResponse) {}
async readText(): Promise<SyncResponseVerifier> {
return new SyncResponseVerifier(await this.response.text());
}
}
// all code in here should be synchronous
class SyncResponseVerifier {
constructor(public text: string) {}
verifyTextContains(value: string) {
return this.text.includes(value);
}
}
您将像这样使用它:
// use the async thing to get the sync thing
async function doThings() {
const asyncRV = new AsyncResponseVerifier({
text: async () =>
"an important forum raising awareness about serious things"
});
const syncRV = await asyncRV.readText();
syncRV.verifyTextContains("rum raisin");
}
否则,您将获得一个分裂性格的班级,该班级的某些事情应该await
进行,而其他事情则不应该。即使您能弄清楚如何使编译器跟踪哪个是哪个(并且正如我在顶部所述,我认为您也无法做到),开发人员可能很难跟踪。
无论如何,希望能有所帮助。祝你好运!