Wishing for a type-safe way to distinguish native types

I'm drowning in Int array indexes for arrays of different types. I would love to have a type-safe variant of typealias (at least for these types). Currently I use e.g.,

typealias NodeIndex Int
typealias MatcherIndex Int
typealias ItemIndex Int

...
let matcher: MatcherIndex
let index: NodeIndex
let parent: NodeIndex
var matched = [ItemIndex]()
...
matched[index] = ... // ARGH! no help from compiler

(I'm drawn to parallel-array structures of late.)

I'd like to see a type definition that

  • has the same implementation shadow as the raw type
  • is treated as a distinct type by the type-checker
  • initializes implicitly from raw type?
  • explicit raw value cast
  • explicit raw value cast for arrays
typedef NodeIndex = Int

let start: NodeIndex = 3
let end: NodeIndex(start.raw + 4) 

let offset: Int = end.raw - start.raw

let data = [NodeIndex](..)

let element: Int = data[0].raw
let vector: [Int] = data.raw

As for alternatives, I noticed String.Index is modeled as an empty frozen struct. Perhaps the runtime cost of an enclosing struct is not bad for smaller data sets, but the array cast is blech.

Corrections welcome: I'm not using the right terminology and might have missed an existing technique or prior discussion. (And if it's not a compelling use-case, I can root around for others.)

Interest? Thoughts?

Thanks!

P.S. - Similar issue: Type Erasure on Built-in And Array Types

A frozen struct with one field (or a frozen enum with one case) has no storage overhead over the type of the single field, and initializing and unwrapping the type should be free since there is no actual representation change.

16 Likes

To check the prior discussions search for newtype in the forums. This seems to be the most recent.

@stephencelis's Tagged is the most well-known attempt at filling this gap, but it won't help with your array indexing issue.

1 Like

You can also use RawRepresentable wrappers if you want more flexibility (at the cost of more boilerplate).

I know it’s been proposed in the past, but I would like to state my hope for a newtype-like keyword that declares the equivalent of a single-member wrapper struct without the possibility of error. The ability to choose the access level of the underlying raw value (newtype(public rawValue) maybe?) would be icing on the cake.