You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unreachable code is not detected for methods that return never #56049
constthrowError=(message: string): never=>{thrownewError(message);}typeThrower=typeofthrowError;consterrorContext={
throwError
};typeErrorContext=typeoferrorContext;consttest1=(thrower: Thrower)=>{thrownewError('foo');// following code results in 7027 "unreachable code detected" as expectedconsole.log('bar');};consttest2=(thrower: Thrower)=>{thrower('foo');// following code results in 7027 "unreachable code detected" as expectedconsole.log('bar');};consttest3=(errorContext: ErrorContext)=>{errorContext.throwError('foo');// following code does NOT result in 7027, although the code is unreachable at runtimeconsole.log('bar');};
🙁 Actual behavior
If a function that returns never is a method, it does not result in error 7027 "unreachable code detected" or any
expected type-narrowing for subsequent code when called.
🙂 Expected behavior
Any code after a call to a function that always returns never should result in error 7027 "unreachable code detected" and any expected type-narrowing regardless of whether that function is method or a standalone function.
Interesting thank you - I've just added an explicit type for the errorContext and I can see it resolves the issue. Let me revert to my actual project as don't believe I'm using an implicit type there, so the issue may be more nuanced.
Having looked at my actual code, it seems the same issue and resolution still applies.
The intended pattern looks like this:
errorManager.error(ConcurrencyMessageId._005_CONCURRENCY_REFRESH_REJECTION,serviceError.status,serviceErrorResponse['odata.error']?.code.toString()??'',serviceErrorResponse['odata.error']?.message.value??'',).throw({args: [['httpStatus',Number],['errorCode',String],['errorMessage',String],],});// TS is not aware that core here is unreachable
Where the return type of .error() is inferred based on the arguments provided to it using generic parameters.
Based on your advice, unfortunately it seems the only way to get TS to correctly infer the control flow, is to break up the function chain and explicitly apply that inferred type to the error context:
consterrorContext: IErrorContext<[httpStatus: number,errorCode: string,errorMessage: string]>=errorManager.error(ConcurrencyMessageId._005_CONCURRENCY_REFRESH_REJECTION,serviceError.status,serviceErrorResponse['odata.error']?.code.toString()??'',serviceErrorResponse['odata.error']?.message.value??'',);errorContext.throw({args: [['httpStatus',Number],['errorCode',String],['errorMessage',String],],});// TS is aware that any core here is unreachable
This is obviously quite verbose and a no go for DX given it makes the inference provided redundant by forcing the author to explicitly type it.
So still curious is this is really the intention / expected behaviour here? If so, could it be improved?
Martin Johns (@MartinJohns) I'm curious what is the expected behaviour for explicit type when there are multiple chainable options (I have depth of 2 in my example below). Currently it doesn't have 7027 "unreachable code detected"
I believe it meets all the criterias that you've mentioned above (correct me if I'm wrong)
Activity
MartinJohns commentedon Oct 10, 2023
This is working as intended. See #32695.
Your
errorContexthas an implicit type.patrickkunka commentedon Oct 10, 2023
Interesting thank you - I've just added an explicit type for the
errorContextand I can see it resolves the issue. Let me revert to my actual project as don't believe I'm using an implicit type there, so the issue may be more nuanced.patrickkunka commentedon Oct 10, 2023
Having looked at my actual code, it seems the same issue and resolution still applies.
The intended pattern looks like this:
Where the return type of
.error()is inferred based on the arguments provided to it using generic parameters.Based on your advice, unfortunately it seems the only way to get TS to correctly infer the control flow, is to break up the function chain and explicitly apply that inferred type to the error context:
This is obviously quite verbose and a no go for DX given it makes the inference provided redundant by forcing the author to explicitly type it.
So still curious is this is really the intention / expected behaviour here? If so, could it be improved?
MartinJohns commentedon Oct 10, 2023
It is, and it's done for performance reasons. It's unlikely for change.
Beraliv commentedon Oct 10, 2023
Martin Johns (@MartinJohns) I'm curious what is the expected behaviour for explicit type when there are multiple chainable options (I have depth of 2 in my example below). Currently it doesn't have 7027 "unreachable code detected"
I believe it meets all the criterias that you've mentioned above (correct me if I'm wrong)
TypeScript Playground - https://tsplay.dev/Ndy4dm
MartinJohns commentedon Oct 10, 2023
Having explicit types is just one requirement. See the list above.
Your
prepare()call is interfering with this requirement.Beraliv commentedon Oct 10, 2023
Martin Johns (@MartinJohns) so
errorContext.prepare.throw('bar');would work but as I have a function, it's not allowed. Got you, thankstypescript-bot commentedon Oct 13, 2023
This issue has been marked as "Question" and has seen no recent activity. It has been automatically closed for house-keeping purposes.