type-guards
type-guards copied to clipboard
Allow missing properties when `undefined` would be a valid value?
For a majority of usecases, the following types are treated as equal:
interface Type1 {
x?: number
}
interface Type2 {
x: number | undefined
}
The difference that Type2
requires x
to be present on the object, while Type1
allows the object to be empty. There's no difference when accessing type.x
-- the inherited type of such expression would be number | undefined
in both cases.
However, the observable difference occurs when iterating over keys. Object.keys(type)
would in first case return either []
or ['x']
, while in the second case it's guaranteed that the result would be ['x']
, exclusively.
type-guards
currently cannot handle the optional argument right now, forcing the developer to write things like this.
const isType = tg.isOfShape({
x: tg.fp.or(tg.isUndefined, tg.isNumber),
})
type Type = tg.FromGuard<typeof isType>
The issue here is that Type
would be same as Type2
, while the current behavior of the library is that the run-time guard is the same as Type1
(x
is required to exist on the object, even if its value is undefined
).
Maybe it would be a good idea for both the runtime guard and the static type to result in the type Type1 | Type2
. In cases when a key is required to exist (but its value is allowed to be undefined
), the developer would need to make additional runtime checks, without option to rely on static types. I'm not sure yet if this is a good compromise.