|
|
|
|
|
by 59nadir
2616 days ago
|
|
Every language that has generics supports this via phantom type variables that can encode extra information only in the type system alongside some other type, or with a specific newtype keyword that effectively does the same: newtype Pixel = Pixel Int
newtype Em = Em Int
pixelWidthToEm :: Pixel -> Em
pixelWidthToEm (Pixel px) = Em px
You can try to call `pixelWidthToEm` with anything other than pixels and it won't work.More dynamically, with an open type variable that only exists in the type system: data User a =
User { name :: String, socialSecurityNumber :: String }
data LogSafe
data LogUnsafe
logUser :: User LogSafe -> IO ()
logUser = undefined
makeUserLogSafe :: User LogUnsafe -> User LogSafe
makeUserLogSafe = undefined
We can never log the user unless the user is deemed LogSafe and we make functions that produce log safe users that you have to call before hand, in order to make sure that sensitive data isn't printed to logs.These are things that have been around for a long time in almost every type system, but people's general lack of interest in using type systems to help them conspires to keep them in the dark. Here's how you can create a number type distinct from other number types in TypeScript: type DistanceInPixels = number & { readonly __newtype__: "DistanceInPixels" }
And a type alias that allows you to create them: export type Newtype<T, Tag extends string> = T & { readonly __newtype__: Tag }
type Pixels = Newtype<number, "Pixels">
|
|