Los tipos de prueba, también conocidos como tipos testigo o de evidencia, son un patrón de programación en el que la mera existencia de un valor garantiza que un determinado cómputo se ha ejecutado. En Dart 3.0, este patrón se materializa combinando cuatro mecanismos: el modificador final, que impide que la clase se extienda o implemente fuera de su biblioteca; un constructor privado de biblioteca (._()), que bloquea la instanciación externa; la privacidad basada en bibliotecas del lenguaje, que hace estas restricciones absolutas; y un sistema de tipos sólido que detecta cualquier intento de falsificación, incluidos los casts inseguros como as.
El artículo lo ilustra con un sistema de registro de usuarios en el que solo se puede obtener un RegistrationReady si antes se han producido los tipos EmailChecked, PasswordChecked y TermsAccepted, cada uno demostrablemente generado por su función de validación correspondiente. Esto obliga al compilador a garantizar que las comprobaciones se han realizado, sin depender de la documentación ni de la revisión manual. Los tipos de prueba pueden además transportar datos validados, como un ParsedInt que lleva consigo el entero ya parseado, y se aplican también a autorizaciones, donde un Authorized<Document> acredita que el usuario tiene acceso al recurso.
El texto contrasta el soporte de este patrón en otros lenguajes. JavaScript carece por completo de tipos sellados; TypeScript aplica las restricciones solo en compilación, pero el tipado se borra en tiempo de ejecución y los tipos branded son fácilmente eludibles. Python sigue la filosofía de adultos responsables y permite sortear cualquier privacidad. Java dispone de clases finales y constructores privados, pero la reflexión con setAccessible(true) los anula, salvo con un SecurityManager ya deprecado. Kotlin, Scala, C# y PHP heredan el mismo problema por sus APIs de reflexión. Go, en cambio, sí protege los tipos no exportados dentro de un paquete, ofreciendo garantías reales análogas a las de Dart. El autor vincula el patrón con el lema «parsea, no valides» y con la correspondencia de Curry-Howard, y señala limitaciones como el coste de definir un tipo por cada invariante y la inconveniencia de abusar del patrón en APIs públicas, donde puede romper la ergonomía del consumo.
