         
         return data
     }
+
+    /// Adds a type translation mapping to the receiver whereby instances of
+    /// `type` are encoded with `name` instead of their type names.
+    @available(iOS, introduced=7.0, obsoleted=10.0, message="There should be a better way.")
+    @available(OSX, introduced=10.9, obsoleted=10.12, message="There should be a better way.")
+    @available(watchOS, introduced=2.0, obsoleted=3.0, message="There should be a better way.")
+    @available(tvOS, introduced=9.0, obsoleted=10.10, message="There should be a better way.")
+    public func setName<Value: ValueCodable>(name: String, forType type: Value.Type = Value.self) {
+        setClassName(boxedClassNameFor(String(type)), forClass: CodingBox<Value>.self)
+    }
     
 }

        return try unarchiver.decodeTopLevelValue(forKey: NSKeyedArchiveRootObjectKey)
    }

}

extension NSKeyedArchiver {


private extension NSCoder {

    func boxedClassNameFor(name: String) -> String {
        return "Encoded<\(name)>"
    }

    func byDecodingBox<Value: ValueCodable>(@noescape body: NSKeyedUnarchiver throws -> CodingBox<Value>?) rethrows -> Value? {
        assert(allowsKeyedCoding)

        guard let archiver = self as? NSKeyedUnarchiver else { return nil }
        archiver.setType(Value.self, forTypeName: String(Value.self), force: false)

        guard let boxed = try body(archiver) else { return nil }
        return boxed.value
    }

    func encodeBox<Value: ValueCodable>(@autoclosure withValue getValue: () -> Value, @noescape body: (NSKeyedArchiver, CodingBox<Value>) throws -> Void) rethrows {
        assert(allowsKeyedCoding)

        guard let archiver = self as? NSKeyedArchiver else { return }
        archiver.setName(String(Value.self), forType: Value.self)

        return try body(archiver, .init(getValue()))
    }
