Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asserts on this from a member function does not narrow this #44212

Open
JarekToro opened this issue May 22, 2021 · 2 comments
Open

Asserts on this from a member function does not narrow this #44212

JarekToro opened this issue May 22, 2021 · 2 comments
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@JarekToro
Copy link

JarekToro commented May 22, 2021

Bug Report

🔎 Search Terms

  • assert type guard
  • this type guard

possibly related to #43368

🕗 Version & Regression Information

Seems to effect all versions

⏯ Playground Link

Playground link with relevant code

💻 Code

/* Setup */
class SuccessResult<T> {
  success: true = true;
  constructor(public value: T) {}
  throwOnFailure(): asserts this is SuccessResult<T> {}
  isSuccess(): this is SuccessResult<T> {
    return this.success;
  }
}

class FailureResult<T, E extends Error> {
  success: false = false;
  constructor(public error: E) {}
  throwOnFailure(): asserts this is SuccessResult<T> {
    throw this.error;
  }
  isSuccess(): this is SuccessResult<T> {
    return this.success;
  }
}

type OperationResult<T = never, E extends Error = Error> =
  | SuccessResult<T>
  | FailureResult<T, E>;

function workingAssertGuard<T>(result: OperationResult<T>): asserts result is SuccessResult<T> {
  if (!result.success){
    throw result.error
  }
}
/* End Setup */



const result: OperationResult<string> = {} as OperationResult<string>

/* This is the issue */
function assertThisType(){
  result.throwOnFailure()
  // type is unchanged
  result // OperationResult<string, Error>
}
/* End of issue */


/* The rest below works as intended */
function narrowOnProperty(){
  // Working narrowing from prop
  if (result.success){
    result.value // SuccessResult<string>
  } else {
    result.error // FailureResult<string, Error>
  }

}

function assertTypeGuard(){

  // Working narrowing from Assert Type Guard Function 
  workingAssertGuard(result)
  result.value // SuccessResult<string>

}

function narrowThisTypeGuard(){
 // Working narrowing from boolean Type Guard Member Function 
    if (result.isSuccess()) {
    result.value // SuccessResult<string>
  } else {
    result.error // FailureResult<string, Error>
  }
}

🙁 Actual behavior

Asserts on this from a member function does not narrow this

🙂 Expected behavior

Asserts on this from a member function does narrow this

@RyanCavanaugh RyanCavanaugh added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels May 27, 2021
@RyanCavanaugh
Copy link
Member

For performance reasons, method-based control-flow-affecting calls need to be immediately (definition left intentionally vague) resolvable to something with an asserts return type to be considered part of the control flow graph. A union type doesn't currently fit that definition, but possibly we could change that.

@JarekToro
Copy link
Author

Thanks @RyanCavanaugh for the explanation. Is there any docs/code that helps explain this? I'd like to look into it some more but wouldn't know where in the codebase to start.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants