I have some values in TypeScript that are only needed within the type system. I'm looking for a way to void the values without forgetting their type. The function bury in the example below is expected to replace the runtime value with undefined and cast it into a tombstone for the buried type. However, my example implementation of Tombstone is not sufficient because Tombstone<{ id: string }> equals void which equals Tombstone<{ id: number }>. What would be a good way to distinguish between buried values? I'd like to avoid confusing developers and wasting runtime memory with values that are only needed for type checking.
type Tombstone<_A> = void
function bury<A>(_value: A): Tombstone<A> {
return undefined as Tombstone<A>
}
type Item = { id: number }
const correct: Tombstone<Item> = bury({ id: 123 })
const incorrect: Tombstone<Item> = bury({ id: 'abc' }) // <- should not work
type Special = Item & { meta: string }
const correct2: Tombstone<Item> = bury({ id: 123, meta: 'test' })
const correct3: Tombstone<Special> = bury({ id: 123, meta: 'test' })
const incorrect2: Tombstone<Special> = bury({ id: 123 }) // <- should not work