Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to indicate that path is unreachable in TypeScript

Tags:

typescript

I have some TypeScript code that looks essentially like this:

if( ... ) 
    result = $(document.createElement("div")) ;
} else if( ... ) {
    result = $(document.createElement("div")) ;
} else {
    assert.unreachable( "Unknown label in buildHTML.") ;
}
result.attr( "data-childNumber", childNumber.toString() ) ; 

The return type of assert.unreachable is never.

There is an error on the last line:

Variable 'result' is used before being assigned.

It seems to me that the never result from assert.unreachable should tell the compiler that there is no path out of the else part.

I know that I can suppress the error by adding throw null; at the end of the else, but this seems inelegant.

A similar problem comes up in the definition of unreachable. It looked like this

export function unreachable( message? : string ) : never {
    if( message===undefined ) message = "Unreachable code reached." ;
    else message = "Unreachable code reached: "+message ;
    raiseTheAlarm( message ) ;
}

where the result type of raiseTheAlarm is never. In this case, I got an error:

A function returning 'never' cannot have a reachable end point.

I fixed this by adding a return keyword before the call to raiseTheAlarm. This looks a bit odd. (Of course, throw null; after the call would also have worked.)

Is there a better way to tell the compiler that a point in the code is not reachable?

like image 570
Theodore Norvell Avatar asked Oct 17 '22 11:10

Theodore Norvell


2 Answers

It seems to me that the never result from assert.unreachable should tell the compiler that there is no path out of the else part.

It works the other way round. When compiler detects that some path is unreachable, it infers never type for variables referenced in that path, if it can. You can use it to enforce that your code handles all possible values for enum or union type, as explained here.

However, compiler does not use information that some path is unreachable when it checks that variable is not used before it's initialized. The solution is simple - you can assign never value to that variable in the unreachable path. As explained in the answer linked above, never was made assignable to any other type specifically for this purpose.

if( ... ) 
   result  = $(document.createElement("div")) ;
} else if( ... ) {
    result  = $(document.createElement("div")) ;
} else {
    result = assert.unreachable( "Unknown label in buildHTML.") ;
}
result.attr( "data-childNumber", childNumber.toString() ) ; 

A problem with your unreachable function is fixed in the same way - it should have

return raiseTheAlarm( message ) ;

as the last statement.

like image 179
artem Avatar answered Oct 21 '22 03:10

artem


There are at least three options

(a)

else {
    return assert.unreachable( "Unknown label in buildHTML.") ;
}

(b) (from @artem's answer)

else {
    result = assert.unreachable( "Unknown label in buildHTML.") ;
}

(c)

else {
    assert.unreachable( "Unknown label in buildHTML.") ;
    throw null ;
}

I went with option (a).

like image 30
Theodore Norvell Avatar answered Oct 21 '22 05:10

Theodore Norvell