Diseñar mejores APIs con Typed Throws

Libranner Santos
26 febrero, 20253min de lectura
Crear código que sea difícil de malinterpretar es una tarea esencial para todos los desarrolladores al diseñar APIs. Antes del lanzamiento de Swift 6.0, no era posible especificar de manera explícita el tipo de errores que una función podía retornar. Sin embargo, ahora esto es posible gracias al concepto de Typed Throws (Excepciones Tipadas).
Ejemplo Práctico con Typed Throws
Imaginemos un escenario en el que definimos un enum
para especificar los tipos de errores que pueden ocurrir en nuestro código. En este caso, trabajamos con una función que realiza una migración. Si ciertas condiciones no se cumplen, la función puede arrojar dos errores: notReady
o outOfDate
.
enum MigrationError: Error {case notReadycase outOfDate}
La función que puede retornar estos errores se escribe de la siguiente manera:
func migrate() throws {if isNotReady {throw MigrationError.notReady}if date < Date() {throw MigrationError.outOfDate}}
Esta implementación tiene dos condiciones claras que, al cumplirse, generan un error. Sin embargo, en versiones anteriores de Swift, no era intuitivo para alguien que no escribió el código identificar qué tipos de errores podían ser arrojados, especialmente si la función tenía muchas líneas de código.
Usando Typed Throws
Así es como luce la función utilizando Typed Throws:
// 1func migrate() throws(MigrationError) {if isNotReady {// 2throw .notReady}if date < Date() {throw .outOfDate}}
En este código, hay dos aspectos clave que destacar:
- Ahora, junto con
throws
, especificamos entre paréntesis el tipo de error que la función puede arrojar:MigrationError
. - Ya no es necesario incluir el nombre del
enum
al usarthrow
, porque el tipo de error se infiere automáticamente. Por lo tanto, simplemente escribimosthrow .notReady
.
Beneficios de Typed Throws
Este cambio no solo mejora la claridad visual del código, sino que también comunica de manera precisa a los usuarios qué errores pueden esperar. Además, limita a los desarrolladores que trabajen en el mismo código a solo retornar excepciones incluidas en MigrationError
.
Si intentamos lanzar un error que no pertenece a MigrationError
, Swift generará el siguiente error en tiempo de compilación: Thrown expression type '...' cannot be converted to error type 'MigrationError'.
Pruebas Unitarias con Typed Throws
Otra ventaja importante de Typed Throws es la facilidad para escribir pruebas unitarias en Swift. Aquí tienes un ejemplo de cómo probar la función anterior utilizando Swift Testing:
@Test func migrate() throws {#expect(throws: MigrationError.self, "Out of date") {try manager.migrate()}}
En este caso, la prueba verifica que se arroje un error del tipo MigrationError
si las condiciones lo requieren.
También puedes evaluar que se arroje un error en concreto, por ejemplo, cambiando el código anterior para usar MigrationError.notReady
como el error esperado:
#expect(throws: MigrationError.notReady, "Out of date") {try manager.migrate()}
Conclusión
Las Excepciones Tyipadas (Typed Throws) son una herramienta útil para desarrollar APIs más expresivas y brindar claridad al código.
Si quieres saber más sobre Swift Testing, te recomendamos este artículo.