Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Java 14 does have something similar

https://openjdk.java.net/jeps/305



No, Java requires you to redefine the variable, i.e.

  if (obj instanceof String s) {
    // s is a String here, but obj is not
  }


That I would say still counts as “similar” not “the same”


That’s the same, just that the scoped definition is implicit.


No, that's the entire point of my question. In Typescript (and Kotlin, as others have noted), the type system knows within the scope of that if statement that obj is a string, so it lets you call string-specific methods on obj withOUT introducing the new variable s.


What I'm saying is that this:

  if (typeof obj === 'string') {
    // obj is a string
  }
is really not anything meaningfully different than this

  if (obj is string as obj) { // as in C#
    // obj is a string (shadowing the outer scoped obj)
  }
or this

  if (obj instanceof String obj) {
    // obj is a String here
  }
you can imagine a pseudo TypeScript language like this

  if (typeof obj === 'string' as obj) {
    // obj is a string
  }
Actual TypeScript merely allows you to elide the "as obj" and all it needs to trigger this is the "typeof obj === <string literal>" inside of an if expression. This can be done by a simple syntactic replacement, it doesn't require control flow analysis to get this specific feature. But yes, if you have a more general computed expression, that would apply, but that was not the case you were stating. Ie the variable isn't the issue (redefining in this case seems like a distinction without a difference)... However this does work in TS, which is a demonstration of CFA:

  const isStr = typeof obj === "string";

  if (isStr) {
    // obj is str
  }
For what it's worth I think CFA is useful in TypeScript based on it at its core being a structural typed bandaid over JS, but I think these specific CFA type narrowing features are redundant in stronger typed languages.


Java cannot do the same without breaking backwards compatibility, hence the idea to introduce a variable explicitly.


but is it a deep copy??


It is not a copy. It still references the same object.


F# also has:

  let foo : obj = failwith ""

  match foo with
  | :? SomeType as blah ->
      // use blah : SomeType
(You're allowed to just use the identifier `foo` in the match arm.)


As does Scala:

  match thing {
    case a: String => 
      // use a as string
    case a @ MyCaseClass(b: String, c, d) =>
      // use a as the instance of MyCaseClass or use b as a string
  }




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: