Typed Racket provides some additional utility functions to facilitate typed programming.
See also the cast form.
(with-asserts ([id maybe-pred] ...) body ...+)
(typecheck-fail orig-stx maybe-msg maybe-id)
| msg-string maybe-id =
| #:covered-id id
> (define-syntax (cond* stx) (syntax-case stx () [(_ x clause ...) #`(cond clause ... [else (typecheck-fail #,stx "incomplete coverage" #:covered-id x)])]))
> (define: (f [x : (U String Integer)]) : Boolean (cond* x [(string? x) #t] [(exact-nonnegative-integer? x) #f]))
eval:10:0: Type Checker: incomplete coverage; missing
coverage of Negative-Integer
These utilities help interface typed with untyped code, particularly typed libraries that use types that cannot be converted into contracts, or export syntax transformers that must expand differently in typed and untyped contexts.
(require/untyped-contract maybe-begin module [name subtype] ...)
| (begin expr ...)
If an identifier name is imported using require/untyped-contract, reexported, and imported into typed code, it has its original type, not subtype. In other words, subtype is used only to generate a contract for name, not to narrow its type.
Because of limitations in the macro expander, require/untyped-contract cannot currently be used in typed code.
(define-typed/untyped-identifier name typed-name untyped-name)
Avoid this if possible. Use only in cases where a type has no subtype that can be converted to a contract; i.e. cases in which require/untyped-contract cannot be used.
This is the nuclear option, provided because it is sometimes, but rarely, useful. Avoid.