最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Function to test variable type or throw in TypeScript? - Stack Overflow

programmeradmin0浏览0评论

I want to have a function to test if a class variable is not null and use it in follow up function calls. But got TS plaints. Encapsulate this validate function because I need to call it in many of my methods.

class A {
  point: Point | null
  validatePoint() {
    if (!this.point) throw new Error()
  }

  update(p: Point | null) {
    this.validatePoint()
    // ts plains this.point can be null
    doSomething(this.point)
  }
}

I want to have a function to test if a class variable is not null and use it in follow up function calls. But got TS plaints. Encapsulate this validate function because I need to call it in many of my methods.

class A {
  point: Point | null
  validatePoint() {
    if (!this.point) throw new Error()
  }

  update(p: Point | null) {
    this.validatePoint()
    // ts plains this.point can be null
    doSomething(this.point)
  }
}
Share Improve this question edited Jul 5, 2020 at 18:43 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Nov 24, 2019 at 7:50 MengoMengo 1,2771 gold badge12 silver badges28 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 6

Typescript 3.7 introduces assertions in control flow analysis:

class A {
    point: Point | null = null;
    validatePoint(): asserts this is { point: Point} {
        if (!this.point) throw new Error()
    }

    update(p: Point | null) {
        this.validatePoint()
        // now ts is sure that this.point can't be null
        doSomething(this.point)
    }
}

Playground

One option is to use a type guard instead, and throw in update instead of validatePoint:

class A {
    point: Point | null;
    validatePoint(p: Point | null): p is Point {
        return Boolean(this.point);
    }
    update(p: Point | null) {
        if (!this.validatePoint(this.point)) {
            throw new Error();
        }
        doSomething(this.point);
    }
}

But using a separate method for something like this seems a bit overkill:

update(p: Point | null) {
    if (this.point === null) {
        throw new Error();
    }
    doSomething(this.point);
}

If you have to put it in a separate function, then another option is for validatePoint to return the validated point (since this sort of thing can't be used to narrow the type of a parent object IIRC):

class A {
    point: Point | null;
    validatePoint() {
        if (this.point === null) {
            throw new Error();
        }
        return this.point;
    }
    update(p: Point | null) {
        const validatedPoint = this.validatePoint();
        doSomething(validatedPoint);
    }
}

You should be explicitly checking for null using an if(this.point === null) statement. Although I don't think you need a separate method for this, it seems a bit overkill.

In update, you validate if this.point is null.

If this.point is null, an error is thrown and doSomething is not invoked. If this.point is not null, that means this.point is Point type.

So it is not possible that this.point is null, when doSomething is invoked. That's why TS plains like that.

发布评论

评论列表(0)

  1. 暂无评论