Skip to content

Narrowing breaking changes #7662

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

Closed
mhegazy opened this issue Mar 23, 2016 · 7 comments
Closed

Narrowing breaking changes #7662

mhegazy opened this issue Mar 23, 2016 · 7 comments
Labels
Breaking Change Would introduce errors in existing code

Comments

@mhegazy
Copy link
Contributor

mhegazy commented Mar 23, 2016

This is a place holder for changes to the type narrowing behavior in TypeScript 2.0:

  • Generic type parameters are now narrowed
function g<T>(obj: T) {
    var t: T;
    if (obj instanceof RegExp) {
         t = obj; // RegExp is not assignable to T
    }
}

See the explanation by @Arnavion in #7719 (comment)

  • Type narrowing does not work for catprued variables in functions and class expressions
export class Class {
    constructor(public p) { }
}

var c: Class | string;
var x: Class;

if (c instanceof Class) {
    function inner() {
        x = c; // Error, type of c is not narrowed, c is Class | string
    }
    x = c; // OK, c is Class
}
@mhegazy mhegazy added the Breaking Change Would introduce errors in existing code label Mar 23, 2016
@mhegazy mhegazy added this to the TypeScript 2.0 milestone Mar 23, 2016
@mhegazy mhegazy closed this as completed Mar 23, 2016
@ivogabe
Copy link
Contributor

ivogabe commented Mar 24, 2016

In the first example obj should be narrowed to T & RegExp, that seems more correct. Is that doable?

@mhegazy
Copy link
Contributor Author

mhegazy commented Mar 24, 2016

narrowing makes the type more "specific", this seems like expanding the domain of the type.

@ivogabe
Copy link
Contributor

ivogabe commented Mar 24, 2016

I thought that "more specific than" means "subtype of". That would mean that narrowed types are always a subtype of their original type and also always assignable to the original type. RegExp is not a subtype of all possible types for T, since it is a type argument, but T & RegExp is a subtype of it. Or is there something that I missed?

@mhegazy
Copy link
Contributor Author

mhegazy commented May 13, 2016

Type parameter narrowing is tracked by #8563

@Strate
Copy link

Strate commented Jun 10, 2016

Can typescript track that variable isn't changed after bypassing to callback and keep that narrow inside callback?
i.e:

{
  let aOrB: A|B = getAOrB()
  if (isA(aOrB)) {
    performOperationA(() => aOrB /* is A here */)
  } else {
    performOperationB(() => aOrB /* is B here */)
  }
  // there is no write-aware operations on aOrB after this point,
  // seems that typescript may be able to catch this case and keep var narrow inside callbacks.
}

@mhegazy
Copy link
Contributor Author

mhegazy commented Jun 10, 2016

Can typescript track that variable isn't changed after bypassing to callback and keep that narrow inside callback?

it can be done, but that is not trivial amount of computing, and would impact compilation times for all projects.

@Arnavion
Copy link
Contributor

@Strate In that case you can yourself use const instead of let and get that behavior.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Breaking Change Would introduce errors in existing code
Projects
None yet
Development

No branches or pull requests

4 participants