Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optional type guard #37

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

RebeccaStevens
Copy link
Contributor

This adds the function tg.optional which takes a type guard as an argument and returns an optional version of that typegaurd.

This allows isOfShape to handle optional properties.

fix: #35
re: #36

Guard Type
tg.isOfShape({ a: tg.optional(tg.isNumber) }) { a?: number }
tg.isOfShape({ a: tg.isOneOf(tg.isNumber, tg.isUndefined) }) { a: number | undefined }

src/index.spec.ts Outdated Show resolved Hide resolved
src/index.spec.ts Outdated Show resolved Hide resolved
src/index.ts Outdated
@@ -139,6 +139,24 @@ export function isArrayOf<T> (itemGuard: Guard<T>): Guard<T[]> {
return ((input: any) => Array.isArray(input) && input.every(itemGuard)) as Guard<T[]>
}

const optionalSymbol = Symbol('optional')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of using a symbol for identify "optional type guards" as it means only type guards that go through the "optional" function defined by this library are considered "optional type guards".

This symbol could possibly be exported so that others can use it but I think it would be best to remove it all together. However to remove it, an alternative implementation of isOptional or the part of isOfShape that uses isOptional would be needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One possible solution would be to introduce a new type for Guards with options and allow this type to be used in a Shape. "optional" could then simply be an option for guards.

The type could possibly just be a tuple like this:

type GuardWithOptions<T> = [Guard<T>, GuardOptions]
type GuardOptions = {
  optional?: boolean
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the mentioned drawbacks with the symbol, but I think it's fine for this library. Something more robust (like a full-blown validation library) would probably benefit from a more complex approach; type-guards is supposed to be a quick utility to help with basic validation (“binary” validation I guess, since it's either a pass or fail, i.e. no specific errors/messages of why it failed).

tsconfig.json Outdated Show resolved Hide resolved
@RebeccaStevens

This comment has been minimized.

README.md Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
src/types.ts Outdated Show resolved Hide resolved
@RebeccaStevens RebeccaStevens force-pushed the issue/35/isOptional branch 2 times, most recently from f68cee2 to a717e61 Compare August 20, 2020 01:22
@RebeccaStevens
Copy link
Contributor Author

@lazarljubenovic Discovered a bug with regard to the typings.
The returned guard type of isOfShape still has the optional keys typed as key: type | undefined rather than key?: type.
Unfortunately we can't solve this issue with the same sort of symbol hack that was used to solve the actual implementation. Another new approach might be needed.

This whole optional problem thing is proving much harder than I thought it would be. 😞

@lazarljubenovic
Copy link
Owner

@RebeccaStevens Yeah, the problem makes me rage quit every time I have a stab at it 😄 This might help with what you mention but I had troubles wrapping my head around the whole thing in combination with type guards. Maybe you'll have more luck 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

"isOfShape" should allow keys not to be specified if that key can be undefined
2 participants