- 
  Notifications
 You must be signed in to change notification settings 
- Fork 1.1k
Support for literal template strings? #14221
-
Now that we have literal types in scala, we can define a type as a set of possible literal values as union of literal values
// Scala 3 type Prime = 2 | 3 | 5 | 7 var prime: Prime = 7 // valid prime = 2 // valid prime = 6 // invalid
However, there may be case where we want to define a pattern-based set of literal values like a set of gray tones for a UI theme :
{ "gray-50", "gray-75", "gray-100", "gray-200" }
One may wonder if there is a way to express this literal set using a string pattern like interpolation or regex, indeed, typescript already implemented a way for expressing this string patterns as Template Literal Types
// TypeScript type ranges = '50' | '75' | '100' | '200' type grays = `gray-${ranges}` /** Generated type * type grays = "gray-50" | "gray-75" | "gray-100" | "gray-200" */
Some other examples of use cases will range from
Define names of events or error (useful in scala.js environments where JavaScript events names are passed as string) like
// JavaScript person.on("age-changed", newAge => { if (newAge < 0) { console.warn("warning! negative age"); } })
where you may have an event name for each person property like name-changed | age-changed | friends-changed then the function parameter can be typed as a literal set defined as regex or interpolation like ${prop}-changed
Regex logic may be useful for defining the set of strings composed of alphanumeric characters of length 2 by using [\w+]{2} however this is way more complex than interpolation.
From the Programming is Scala book by @odersky section 5.3
In Scala, string interpolation is implemented by rewriting code at compile time. The compiler will treat any expression consisting of an identifier followed immediately by the open double quote of a string literal as a string interpolator expression. The s, f, and raw string interpolators are implemented via this general mechanism. Libraries and users can define other string interpolators for other purposes.
Could a custom type interpolator be defined as mechanism for template literal types?
type Grays = s"gray-${50 | 75 | 100 | 200}." // type Grays = "gray-50" | "gray-75" | "gray-100" | "gray-200"
Beta Was this translation helpful? Give feedback.
All reactions
you can do this with a match type:
import scala.compiletime.ops.string.+ type OfString[S <: String] = S type Spread[S <: String, T <: NonEmptyTuple] = T match case OfString[t] *: EmptyTuple => S + t case OfString[t] *: ts => (S + t) | Spread[S, ts] type Grays = Spread["gray-", ("50", "75", "100", "200")] val `gray-50`: Grays = "gray-50"
then you can use this as a template to support more than one splice
Replies: 1 comment
-
you can do this with a match type:
import scala.compiletime.ops.string.+ type OfString[S <: String] = S type Spread[S <: String, T <: NonEmptyTuple] = T match case OfString[t] *: EmptyTuple => S + t case OfString[t] *: ts => (S + t) | Spread[S, ts] type Grays = Spread["gray-", ("50", "75", "100", "200")] val `gray-50`: Grays = "gray-50"
then you can use this as a template to support more than one splice
Beta Was this translation helpful? Give feedback.
All reactions
- 
 👍 5