Type enforcing for type aliases

Why doesn't Swift enforce type matching policy for typealiases? What was the decision behind this?

typealias MeaningfulType = String

func process(value: MeaningfulType) {}

I can now call process with both random String object and MeaningfulType objects, and even though they are actually the same thing, I expected Swift to force type check for me. The reason: I want to be sure only MeaningfulType objects from a specific source are accepted by process(), and any other random string would cause compiler error.

1 Like

Without this type check I have to introduce a wrapper around String and that looks a bit dirty.

Type alias is, quite literally, just an alias. It’s as if you just type String wherever you type MeaningfulType.

As you said, you’ll need to write a wrapper around the type you want. It could be troublesome at times, but performance-wise, it’s free.

6 Likes

The feature you want is called newtype in other languages. It was pitched on this forum in the past, you can read these for more insight.

4 Likes

As cukr said, newtype sounds like what you're thinking of. Many folk want it.

The way to get most of the behavior you're after is

struct MeaningfulType {
    var value: String
}

My understanding is that the compiler recognizes that there is only one member so it doesn't take any extra space. The only downside is having to reach into MeaningfulType's value member.

4 Likes

As of Swift 5.1, that can be fixed with @dynamicMemberLookup:

@dynamicMemberLookup
struct MeaningfulValue {
  private var value: String
  public init(_ value: String) { self.value = value }

  public subscript<U>(dynamicMember keyPath: KeyPath<String, U>) -> U {
    return value[keyPath: keyPath]
  }
  public subscript<U>(dynamicMember keyPath: WritableKeyPath<String, U>) -> U {
    get { return value[keyPath: keyPath] }
    set { value[keyPath: keyPath] = newValue }
  }
}
1 Like
Terms of Service

Privacy Policy

Cookie Policy