What is this Kotlin type: (String..String?)
Asked Answered
A

1

6

IntelliJ is showing me context hints that my variables are of type (String..String?). I cannot find any mention of it on the internet, what is this type?

enter image description here

Accouchement answered 12/2, 2022 at 20:4 Comment(8)
What is the type of payload.email?Momentum
@Momentum It is public String getEmail(). It might be a Java-Kotlin translationAccouchement
Is the type definition written in Java, by any chance? When using Java from Kotlin types are often written as String! because Kotlin cannot know if these platform types are nullable or not. Maybe that is a different notation for it? It would make some sense, meaning any type between non-nullable and nullable String. However, I've never seen this representation myself.Momentum
I don't think it's valid Kotlin code: playground. Mysterious.Nougat
@Nougat It's a hint by IntellJ IDEA, not Kotlin code. IntelliJ also uses String! to denote platform types, which is not valid Kotlin syntax either.Momentum
Are you able to write val email: String? = payload.email?Momentum
what do email is String and email is String? return? 2xtrue means it's String, false true that it's String?, 2xfalse - no clue (see pl.kotl.in/ymOft6Bp7). My gut feel says it's related to the Java not being null specificRapp
@Rapp this is not correct. Those is checks will depend on the current value returned by payload.email, not its type. So you'll get true/true if email is not null at this moment, and get false/true if email is null. In the first case, you can't assume the string could never have been null. You can't know the actual intended type unless you look at the corresponding Java code and its invariants/intentionFlagella
F
6

(String..String?) represents a flexible type with lower bound String and upperbound String? (nullable string). This is not valid Kotlin code (it's not denotable) but it is used in the compiler internals and thus in IntelliJ's hints sometimes.

(On the JVM we often see platform types using ! as in String!, which are a more specific case of flexible types)

It's Kotlin's way of saying it doesn't know whether the String type declared for payload.email is nullable or not (for instance if this is declared in Java, which doesn't distinguish those), and yet it doesn't want to enforce either of those, for convenience (hence "flexible").

As the name suggests, flexible types are flexible — a value of type (L..U) can be used in any context, where one of the possible types between L and U is needed

This means that even though the actual type of the value is "somewhere between String and String?", values of this type can be used even in places expecting String, even though the real type of that value may be String? and thus the value could be null.

This is useful because assuming it is String would mean that null checks would be marked as redundant, and assuming it is String? would force the developer to write null checks everywhere, even though they might know that this particular Java method cannot return null.

In general, it's a good practice to explicitly declare the type of a variable that you get from Java, to avoid the propagation of the platform type and the uncertainty (and unsafety) that comes with it:

val email: String = payload.email // if you know it cannot be null
val email: String? = payload.email // if you don't know
Flagella answered 12/2, 2022 at 22:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.