镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Should error when unwrapping an unwrappable variable #8453

Description

@tinganho

s cannot be null or undefined below. So I think it is appropriate to error when trying to unwrap.

let s: string;
id = '';
if (s!) { // should throw an error

}

Activity

  1. basarat commented on May 4, 2016

    @basarat
    Contributor

    I think you meant :

    let s: string;
    s = '';
    if (!s) { // should throw an error
    
    }

    That said it can cause issues as people might try defensive coding due to external influences e.g. #8452 now allows people to do null/undefined checks even though they are not in the domain of the type 🌹

  2. tinganho commented on May 4, 2016

    @tinganho
    ContributorAuthor

    Basarat Ali Syed (@basarat) I actually meant s!.

  3. basarat commented on May 4, 2016

    @basarat
    Contributor

    Basarat Ali Syed (@basarat) I actually meant s!.

    Isn't it a syntax error?

    image

  4. tinganho commented on May 4, 2016

    @tinganho
    ContributorAuthor

    I'm not getting any error. The unwrap operator removes undefined | null from the type:

    screen shot 2016-05-04 at 12 11 11

  5. basarat commented on May 4, 2016

    @basarat
    Contributor

    Indeed not an error on master

    image

    Apparently its a NonNullExpression (like you said, to remove undefined | null from the type, a TypeScript type system thing) as opposed to a PrefixUnaryExpression (a JavaScript thing). I've got some searching to do. Sorry for misunderstanding 🌹

  6. basarat commented on May 4, 2016

    @basarat
    Contributor

    Got it. I really should have read #7140 better instead of winging it 🌹

    image

    Did spend some time searching for "unwrap operator" :)

  7. tinganho commented on May 4, 2016

    @tinganho
    ContributorAuthor

    Did spend some time searching for "unwrap operator" :)

    Sorry might have used the wrong terminology. Non-null assertion operator is more correct.

  8. RyanCavanaugh commented on May 4, 2016

    @RyanCavanaugh
    Member

    We allow benign coercions everywhere else (e.g. unary + is valid on number, you can type-assert to the same type, etc) and it doesn't seem to be much of a problem. What's the reasoning to disallow this one?

  9. tinganho commented on May 5, 2016

    @tinganho
    ContributorAuthor

    Ryan Cavanaugh (@RyanCavanaugh) I would like if TS did the same with the two example you mentioned. Though I think the unwrap operator is different. It is more common. Actually I found out that had a case where a variable where most of the time of type T 99% of the cases and 1% of the cases it was undefined. So spontaneously, I put it as T | undefined. Though I discovered I needed to put ! everywhere. So I then switched it to type it as T instead. During refactor it could really help me if there was errors where ever I put an unnecessary !.

    Besides refactoring benefits, I think it is correct to error just because it is unnecessary operation.

    Swift also errors:
    screen shot 2016-05-05 at 11 22 38

  10. mhegazy commented on May 5, 2016

    @mhegazy
    Contributor

    what about type parameters?

  11. tinganho commented on May 6, 2016

    @tinganho
    ContributorAuthor

    what about type parameters?

    Can you elaborate?

  12. mhegazy commented on May 6, 2016

    @mhegazy
    Contributor
    function f<T>(a: T) {
        return a!; // is this an error or not?
    }
  13. tinganho commented on May 7, 2016

    @tinganho
    ContributorAuthor

    It should error. I think a nullable type argument should be declared at the parameter declaration, because it is more declarative and it is not the call site that decides if it is nullable or not.

    A nullable type passed in a non-nullable type argument function should also error.

    function f<T>(a: T) {
        return a!; // is this an error or not? yes it is
    }
    
    let str: string | undefined;
    f(str); //error str is nullable
    
    function f<T>(a: T | undefined) {
        return a!; // is this an error or not? no it isn't
    }

    FWIW, that is what swift does.

    screen shot 2016-05-07 at 10 53 26

    (Interestingly Swift allows nullable passed as an non-null type argument):

    screen shot 2016-05-07 at 10 54 57

  14. tinganho commented on May 7, 2016

    @tinganho
    ContributorAuthor

    Maybe it is best to expose this feature behind a flag. As CFA improves it will break code that it didn't cover before. In my opinon it is good to error, because devs can learn new CFA:s.

  15. DanielRosenwasser commented on May 9, 2016

    @DanielRosenwasser
    Member

    I think at one point Alex Eagle (@alexeagle) mentioned that if your dependencies weren't updated to use non-null assertions, you could add the assertions as something of a TODO until your dependencies were updated (and if I'm misquoting, feel free to clarify).

    So it seems like using the assertion is okay in some contexts where you're migrating code, but eventually I think you'd want to get rid of any places where you don't really need those assertions. We should consider how often this scenario pops up.

  16. RyanCavanaugh commented on May 16, 2016

    @RyanCavanaugh
    Member

    We're going to leave this as an OK thing to do. In addition to precedence with other allowed facile assertions, the real risk here is that it could make improvements to the control flow analysis into breaking changes, which would be really unfortunate.

  17. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    SuggestionAn idea for TypeScriptWorking as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions