-
Notifications
You must be signed in to change notification settings - Fork 87
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
refactor: nominal typing #2021
refactor: nominal typing #2021
Conversation
@@ -0,0 +1,65 @@ | |||
import { identity } from 'lodash' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think you are overcomplicating this. why can't we just use type-fest's Opaque
type instead of a relatively unused and not-updated library?
to create an opaque type, we just need a creator method, e.g.
import { Opaque } from 'type-fest'
type Email = Opaque<string, 'Email'>
const createEmail = (email: string): Email => {
// Can even add validation here and throw error or something
return email as Email;
}
you really don't need something so complex like assert, etc.
everything else should stick to the same doesn't it? Only functions that absolutely need the correct type to declare it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the reason why we can't use the Opaque
type is because it's meant as a black box - once we use it, there's no way for us to extract the type out from Opaque
because it's set as Type & {readonly __opaque__: Token}
where there isn't a witness to the base type.
wrt assert
and extract
i just wanted to add utility methods for ppl to use AHAH so that the api is sensible and easy to use
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should not need to extract the type out. any arguments of 'string' (for example) will be able to be used with Opaque<string, 'Key> since the Opaque type is a superset.
@@ -434,15 +432,21 @@ export class MailService { | |||
formData, | |||
}: { | |||
replyToEmails?: string[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this also be of Email[] type
note: this is marked as draft to ensure that the design is sound before fixing up the tests/methods in the controller layer
Problem
Currently, our types for email and mobile phone number are
string
- this results in possibly incorrect definitions where we want to use aEmail
type but we pass in a normalstring
, which is not caught by the type system.a more detailed discussion can be found here!
Solution
ts-brand
to get pseudo nominal typing through the use of a brand.Design Considerations
zod
was not used due to its limitations -z.infer
associates input types with output types of the schema. Hence, even though we validate it, the output is still string, which doesn't help.