Home > Net >  TypeScript narrowing in while loops
TypeScript narrowing in while loops

Time:12-31

When writing while loops, I often run into the situation where I can be sure a certain value exists (connection exists in the example) but the control flow analysis can not narrow it. Here's an example:

    removeVertex(vertex: string) {
        const connections = this.adjacencyList[vertex];
        while (connections.length) {
            const connection = connections.pop(); // <- This can not be undefined
            this.removeEdge(connection!.node, vertex); // <- Unwanted casting
        }
    }

My general escape hatch is to just append ! to signal the compiler that a given type can not be undefined but I'm wondering if there is a more elegant way of solving this.

Edit fixed position of ! as suggested in the comments

CodePudding user response:

(Note: I'm assuming the ! in your question was misplaced, see this comment.)

There are at least a couple of things you can do:

  • You can use a type assertion function
  • You can rewrite the loop (in this particular case)

Type Assertion Function

The type assertion function is an assertion backed up by runtime checking (so you know it isn't incorrect):

function assertNotUndefined<T>(x: T): x is Exclude<T, undefined> {
    if (x === undefined) {
        throw new Error(`Value was undefined`);
    }
}

Then the loop is:

removeVertex(vertex: string) {
    const connections = this.adjacencyList[vertex];
    while (connections.length) {
        const connection = connections.pop();
        assertNotUndefined(connection);
        this.removeEdge(connection.node, vertex);
    }
}

Rewriting the Loop

Another option in this specific case is to rewrite the looop slightly:

removeVertex(vertex: string) {
    const connections = this.adjacencyList[vertex];
    let connection: ConnectionType | undefined;
    while ((connection = connections.pop()) !== undefined) {
        this.removeEdge(connection.node, vertex);
    }
}

...but that's specific to this exact loop. :-)

  • Related