Skip to content

Good Bye Type Error Explosions

Type errors in Filtrera now pinpoint exactly where types diverge instead of dumping entire type definitions side by side.
2 min read

Types are supposed to be your guide. A gentle tap on the shoulder when something doesn’t add up. But when you’re working with deeply nested records, the type checker has had a tendency to drop the gentle act entirely, trading its helpful nudges for something closer to a medieval torture device. Instead of telling you what went wrong, it would hurl two enormous type definitions at your face and say “figure it out yourself”.

The problem

Take this example:

let Profile: {
name: text
age: number
}
let User: {
profile: Profile
}
let myUser = { profile = { name = 'test', age = 'wrong' } }
let f (input: User) => input.profile.name
from f myUser

Before, the error looked like this:

Expected type:
{ profile: {
age: number
name: text
} }
Got:
{ profile: {
age: 'wrong'
name: 'test'
} }

With only two fields this is manageable. But in real world scenarios with records containing dozens of fields, nested several levels deep inside iterators of records of maps, this becomes completely unreadable. You’re left scanning two massive type definitions trying to spot the one field that doesn’t match. The type system, which was supposed to help you, is now actively wasting your time.

The fix

The type checker now structurally compares the expected and actual types and drills down to the exact point of divergence. The same code now produces:

Type mismatch at:
.profile.age
expected: number
got: 'wrong'

Three lines. No noise. Just the path to the problem and what’s wrong.

This works for all complex types, such as records, iterators, maps, and tuples. An iterator of records with a wrong field deep inside? You’ll see [].fieldName pointing straight at the issue instead of two massive type trees.

Tooling support

Filtrera is an embedded language and runtime, so interoperating with the host application and tooling matters. The same type diff API that the parser uses internally is available for host applications to use directly. Parse errors also retain the structured type diff, so tooling can consume the mismatches programmatically and present them however makes sense for the context.