7

being a Typescript rookie, I am trying to type everything as precisely as possible as a part of the learning process.

I have a lqip (low quality image placeholder) property coming from a CMS which should be a base64 encoded image. It is clearly a string, but typing it as a string feels kind of imprecise.

mainImage: Schema.Post["mainImage"] & {
  //  can I be more precise? It should be always a base64 encoded image, not just a generic string…
  // e.g. "data:image/jpeg;base64,/9j/2wBDAAYEB…"
  lqip: string
}

Is there a type for base64 encoded image in Typescript? I've tried to google extensively, but I've found only topics regarding atob/btoa conversions, not the type itself. Thanks!

HynekS
  • 2,738
  • 1
  • 19
  • 34
  • 2
    A string is a string, Typescript doesn't differentiate between the actual value of a type. As Ivan pointed out in this answer it is common practice to just use a type alias so it's a bit more clear what exactly that string should contain. Mind you that this doesn't enforce any value. – Johannes Klauß Apr 03 '21 at 13:00
  • @JohannesKlauß Thank you. I was playing with regexes for a moment, hoping they could help, but as I found out, there are neither currently supported nor useful due to static type checking. Maybe it would be helpful if I'ld test the props PropType (as using React), but I would probably rather trust my CMS. – HynekS Apr 03 '21 at 13:42

3 Answers3

10

For those who is still looking for an answer, you can create your own type

type Base64<imageType extends string> = `data:image/${imageType};base64${string}`

const base64: Base64<'png'> = 'data:image/png;base64test...'

you can try here

tsu
  • 1,122
  • 1
  • 10
  • 22
3

I don't think there is, but you can create your own type that is an alias for a string type, So when you look at your code you can disambiguate between regular string and your base type.

type Base64 = string
mainImage: Schema.Post["mainImage"] & {
  lqip: Base64
}


Ivan V.
  • 7,593
  • 2
  • 36
  • 53
  • Thank you. I was playing with regexes for a moment, hoping they could help, but as I found out, there are neither currently supported nor useful due to static type checking. Maybe it would be helpful if I'ld test the props PropType (as using React), but I would probably rather trust my CMS. – HynekS Apr 03 '21 at 13:42
2

Opaque types can give you extra safety here, while TypeScript does not support them natively, it is possible to hack something together

type Opaque<T, K extends string> = T & { __typename: K }

type Base64 = Opaque<string, "base64">

const decodeBase64 = (base64String: Base64) => {
  return Buffer.from(base64String, "base64").toString("utf8")
}

const str = "a"
decodeBase64(str) // errors

const str2 = "a" as Base64
decodeBase64(str2) // valid

You can now write a type guard or runtime check and assert that a string is Base64 just to have a little more safety