6

Let's say I want to allow a hex string; so the only allowed values would be 0-9a-f. Is there a way in TypeScript to define a type string that only takes certain strings? i.e.

// valid
const valid: HexString = '123abc';
// invalid
const invalid: HexString = 'ijk';

I know Regex type definitions is a proposal here, was wondering if there was a way to achieve this in the meantime.

1 Answer 1

8

Only with "OpaqueTypes" or "Nominal Types" aslong as you have an implementation that can make a string a HexCode the implementation is as follows.

export type Opaque<K, T> = T & { __TYPE__: K };
type HexCode = Opaque<string, "HexCode">

const createHexCode = (str: string): HexCode => {
  // implementation that forces string to be hexCode
  return str.toString() as HexCode // casting is needed.
}
const test = createHexCode("#333");
const isAssignableString: string = test; // yes anything that is HexCode is still technically a string.
const isAssignableHexCode: HexCode = "standard string" // error

this pattern is also useful for things like PositiveInteger and PasswordHash where you don't want anyone to accidentally assign a plain-string to that value you want to force people to use a function that returns a PasswordHash

Sign up to request clarification or add additional context in comments.

3 Comments

Presumably you want the implementation of createHexCode() to throw a runtime error if the passed in string does not match the regex. Or maybe createHexCode() returns a HexCode | undefined. Or even isHexCode(str: string): str is HexCode type guard.
Yeah @jcalz definitely any of those are important i thought i'd leave it up to him, definitely depends on the use-case because even just returning a default can work in alot of use-cases (I.E How games make missing textures default purple or a color that stands out so they can see its missing rather than throw)
type HexCode = Opaque<string, "HexCode">? Did you mean type HexCode = Opaque<"HexCode", string> instead?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.