# Typed Racket guidelines

**URL:** https://racket.discourse.group/t/typed-racket-guidelines/2805
**Category:** Questions & Answers
**Tags:** typed-racket
**Created:** [March 19, 2024, 6:22am UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805 "2024-03-19T06:22:50Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Tyrn](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/tyrn/32/1731_2.png) [@Tyrn](https://racket.discourse.group/u/Tyrn)
#### Post date: [March 19, 2024, 6:22am UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/1 "2024-03-19T06:22:50Z")

</div>

Hi,

Frankly, the question should be "Typed Racket: is it safe to use?". I sensibly asked the [similar question](https://racket.discourse.group/t/lazy-racket-guidelines/2792) about the Lazy Racket, and the unanimous answer was "forget it". Well, not exactly, but unless the general laziness is more than a means to an end for you, better stay away from it.

If I start my project with `#lang typed/racket` at the head of each file, am I going to feel just as happy and optional as with Python type annotations, or there's a price to pay?

---

<div class="post-metadata">

### Author: ![Tyrn](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/tyrn/32/1731_2.png) [@Tyrn](https://racket.discourse.group/u/Tyrn)
#### Post date: [March 19, 2024, 8:59am UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/2 "2024-03-19T08:59:38Z")

</div>

First restriction: type annotations are mandatory. Fortunately, on a per-file basis.

---

<div class="post-metadata">

### Author: ![EmEf](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@EmEf](https://racket.discourse.group/u/EmEf)
#### Post date: [March 19, 2024, 11:35am UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/3 "2024-03-19T11:35:22Z")

</div>

[[You overinterpret the answer concerning `#lang lazy` a bit. You can write cool generally lazy programs in it, if that’s your thing. The interop with strict Racket is the problem, and that’s what you seem to want.]]

Typed Racket is real and usable for any kind of project. It’s type system is sound (modulo bugs). It’’s types are checked at the boundary to untyped modules. Higher-order values are tracked to ensure that they obey the types across boundaries.

What’s the catch? On occasion you may encounter a performance problem if your program’s execution involves a high densitive of mutually recursive typed-untyped calls. Most other performance costs due to checks are tolerable. If you do run intol such performance problems, complain here.

---

<div class="post-metadata">

### Author: ![Tyrn](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/tyrn/32/1731_2.png) [@Tyrn](https://racket.discourse.group/u/Tyrn)
#### Post date: [March 19, 2024, 11:44am UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/4 "2024-03-19T11:44:51Z")

</div>

I suppose the catch you mentioned isn't relevant in case of compiled binaries. Is it really so?

---

<div class="post-metadata">

### Author: ![EmEf](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@EmEf](https://racket.discourse.group/u/EmEf)
#### Post date: [March 19, 2024, 12:09pm UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/5 "2024-03-19T12:09:02Z")

</div>

Racket is complied so I am not sure what you mean. I think the answer is ‘no’.

---

<div class="post-metadata">

### Author: ![Tyrn](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/tyrn/32/1731_2.png) [@Tyrn](https://racket.discourse.group/u/Tyrn)
#### Post date: [March 19, 2024, 12:19pm UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/6 "2024-03-19T12:19:03Z")

</div>

I mean two different cases:

1. You can start a script with a hashbang: `#!/usr/bin/env racket`. This means compile time plus run time.

2. You can make a binary first: `raco exe ...` , run time only.

With typed languages type checking adds to compile time only. Do you mean that with Typed Racket type checking adds to run time in both cases?

---

<div class="post-metadata">

### Author: ![scolobb](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/scolobb/32/108_2.png) [@scolobb](https://racket.discourse.group/u/scolobb)
#### Post date: [March 19, 2024, 12:44pm UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/7 "2024-03-19T12:44:57Z")

</div>

Hi @Tyrn,

Just to complement @EmEf's answer: Typed Racket is great and covers a lot of Racket, but not all of the libraries have types, and converting untyped code to typed code is not automatic. You can import untyped code into typed code by explicitly giving types to the identifiers you import, but you have to write out those types on your own as well.

Personally, I find this a great occasion to contribute to Racket ecosystem and totally worth the additional effort, but this is something you have to factor in your development time.

---

<div class="post-metadata">

### Author: ![EmEf](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@EmEf](https://racket.discourse.group/u/EmEf)
#### Post date: [March 19, 2024, 12:52pm UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/8 "2024-03-19T12:52:20Z")

</div>

Racket compiles code in both cases. Compiling includes type checking.

Run-time checks come in when you link typed and untyped Racket into a single program:.

Say module A is this untyped code:

```scheme
#lang racket 

(provide f)

(define (f x) 
   (+ x 1))

```

and modyle B is typed:

```scheme
#lang typed/racket 

(provide main) 

(require/typed A ;; adjust for concrete file/collects
  [f (-> Integer String)])

(define (main x) 
  (string-append “hello “ (f (* 2 (string->number x)))))

```

The creator of B mistakenly assumes that `f` returns a String. Now run B as a script like this

$ ,/B 10

Facts:

— Both get compiled.  
— A type checks.  
— The call from B to A is fine, because it type checked.  
— The return from A to B sends over 21.

Question: What would you like to happen as someone who equipped B with types?

— Typed Racket inserts a run-time check to make sure that types don’t get usurped.  
— TypeScript does nothing. It happily returns some string from `main`.  
— Python’s types aren’t worth mentioning.

Indeed, TR is the most advanced type system in the world that comes with such checks.

Question: are such checks useful?

Based on some recent research, the answer has to be nuanced:

— for someone who makes a mistake in formulating types for untyped code (like above),  
the information from run-time checks helps.

— for someone who makes a mistake in code (untyped imports typed, calls it with bad arguments),  
the information from run-time checks is still useful but less so.

---

<div class="post-metadata">

### Author: ![hendrikboom3](https://avatars.discourse-cdn.com/v4/letter/h/b5e925/32.png) [@hendrikboom3](https://racket.discourse.group/u/hendrikboom3)
#### Post date: [March 20, 2024, 5:42pm UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/9 "2024-03-20T17:42:41Z")

</div>

you have to write out those types on your bbbown as well.

This can be difficult if the untyped part does not document its data structures.

-- hendrik

---

<div class="post-metadata">

### Author: ![jbclements](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/jbclements/32/11_2.png) [@jbclements](https://racket.discourse.group/u/jbclements)
#### Post date: [March 20, 2024, 8:34pm UTC](https://racket.discourse.group/t/typed-racket-guidelines/2805/10 "2024-03-20T20:34:09Z")

</div>

I'm not sure that anyone here has said this: I believe that Typed Racket is extremely dependable and very widely used, much more so than lazy racket. If you were to make a "Ring 0" / "Ring 1" distinction, I would say that Typed Racket is in ring 0, and lazy racket is in ring 1.

I use Typed Racket constantly. A common use case for me is that I write code hastily in Racket, then come back a year later and can't easily understand what it means and refactor it to be in Typed Racket.

I would say that Typed Racket can impose some irritating code-writing-time overhead in the case of certain racket idioms (uses of higher-order functions like sort, map, and filter can become syntactically heavy (inst is your friend here)), but I absolutely _love_ the ability to hover over an identifier and see what its type is.
