Opaque Types in TypeScript
My favorite feature in Flow is the “opaque type”. Opaque
types may only be created in the file where the opaque type was defined. Which
means you can export one function, createUserName()
, that makes sure your user
name is in the correct format and returns an opaque UserName
type.
TypeScript doesn’t have opaque types, so I simulate them with unique symbols.
type UserName = string & {_opaque: typeof UserName};
declare const UserName: unique symbol;
// Error! `string` is not assignable to `UserName`.
let notUserName: UserName = 'Hello, world!';
// OK
let userName: UserName = createUserName('calebmer');
function createUserName(name: string): UserName {
if (/^[a-zA-Z0-9_-]+$/.test(name)) {
return name as UserName;
} else {
throw new Error('Not a user name!');
}
}