【问题标题】:Typescript doesn't narrow on function constructor打字稿不会缩小函数构造函数
【发布时间】:2022-01-15 17:24:25
【问题描述】:

我正在使用一个名为 DNSHandler 的构造函数,其接口如下所示:

interface DNSHandler {
    received: Partial<DNSStandardQuery>;
    ParseDNSStandardQuery(): boolean;
    __parseDomain(domainBuf: Buffer): string;
}

其中 DNSStandardQuery 的接口包含许多我想在调用 DNSHandler 的ParseDNSStandardQuery() 时填写的属性。

所以在 DNSStandardQuery 的构造函数中,我将 this.received 初始化为一个空对象,并用 DNSBuffer: Buffer 填充它的第一个属性 - rawQuery

this.received = {};
this.received.rawQuery = DNSBuffer;

但是当我在ParseDNSStadndardQuery() 方法中引用this.received.rawQuery 时:

this.ParseDNSStadndardQuery = function() {
    if (this.received.rawQuery.length < 21) {...}
}

我明白了:

Object is possibly 'undefined'. TS(2532)

我知道我明白了,因为 this.received 被声明为 Partial 类型,但我预计它会在构造函数部分中缩小。

我错过了什么?

下面的整个(最小)示例,因为遇到每个 buff = this.received.rawQuery 引用 Object is possibly 'undefined'.ts(2532) 错误:

const DOT_ASCII = 46;


interface DNSStandardQuery{
    rawQuery: Buffer;
    transactiodID: number;
    flags: number;
    questions: number;
    type: number;
    class: number;
    domain: string;
}

interface DNSHandler{
    received: Partial<DNSStandardQuery>;
    ParseDNSStadndardQuery(): void;
    __parseDomain(domainBuf: Buffer): string;
}

const DNSHandler = function(this: DNSHandler, DNSBuffer: Buffer){
    this.received = {};
    this.received.rawQuery = DNSBuffer;
    // Only handles standard queries with single question, with  type 'A' internet class queries.
    this.ParseDNSStadndardQuery = function(){
        let received = this.received;
        let buff = this.received.rawQuery;
        if (this.received.rawQuery.length < 21) {console.error("Got too short message"); return false;}
        received.transactiodID = parseShort(buff[0], buff[1]);
        received.flags = parseShort(buff[2], buff[3]);
        received.questions = parseShort(buff[4], buff[5]);
        received.class = parseShort(buff[buff.length - 2], buff[buff.length - 1])
        received.type = parseShort(buff[buff.length - 4], buff[buff.length - 3])
        received.domain = this.__parseDomain(buff.slice(12, buff.length-4));
    }

    this.__parseDomain = function(domainBuf: Buffer){
        let domain = [];
        let bytesToRead = domainBuf[0];
        while(bytesToRead){
            domain.push(...domainBuf.slice(1, bytesToRead+1) as unknown as number[],DOT_ASCII);
            domainBuf = domainBuf.slice(bytesToRead+1);
            bytesToRead = domainBuf[0];
        }
        // Remove trailed DOT
        return String.fromCharCode(...domain.slice(0, domain.length-1));
    }
} as any as {new(DNSBuffer: Buffer): DNSHandler}

【问题讨论】:

  • 你给我们的代码太少了,你的解释太模糊了,没有填补空白。为什么不在问题末尾发布所有代码?您真正应该做的是提供minimal reproducible example。通过创建minimal reproducible example,您可以将问题缩小到本质,我自己解决问题!
  • received: Partial&lt;DNSStandardQuery&gt; 表示received 可能是一个空对象。您可能在某个时候设置了它,但 TS 无法真正可靠地知道您提到的函数何时被称为您要使用的属性已被定义
  • @Inigo 已更新。感谢您的反馈,这是我的第一个问题 :)
  • @apokryfos 那么在这种情况下建议做什么呢?

标签: javascript typescript es6-class type-narrowing


【解决方案1】:

好的,经过一些尝试为这种情况找到最佳解决方案后,我找到了一个有希望的解决方案

而不是像我以前那样将属性声明为部分属性:

interface DNSHandler{
    received: Partial<DNSStandardQuery>;
    ParseDNSStadndardQuery(): boolean;
    __parseDomain(domainBuf: Buffer): string;
}

你可以用通常的方式声明属性:

interface DNSHandler{
    received: Partial<DNSStandardQuery>;
    ParseDNSStadndardQuery(): boolean;
    __parseDomain(domainBuf: Buffer): string;
}

然后用 {} 语法初始化对象:

const DNSHandler = function(this: DNSHandler, DNSBuffer: Buffer){
    this.received = <DNSStandardQuery>{};
...
}

【讨论】:

    猜你喜欢
    • 2016-09-04
    • 1970-01-01
    • 2023-03-03
    • 2018-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 2022-01-23
    相关资源
    最近更新 更多