6

I'm trying to use the solution posted here to create a GUID-type string in my angular4/TypeScript web app.

Here is the function I'm writing:

function uuidv4() {
  return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  )
}
console.log(uuidv4())

TypeScript is giving me the following error:

Operator '+' cannot be applied to types 'number[]' and '-1000'.

What do I need to change to make this TS compatible?

Thanks!

Basya Rosemann
  • 180
  • 2
  • 14
  • I suppose the error points to another location in your code. Search for "-1000" – hgoebl Jul 20 '17 at 08:30
  • I second that what @hgoebl has said. The issue is somewhere else. https://plnkr.co/edit/MxwthKjqxCWRAicGtcXV. Please provide andular2 code. – The Hungry Dictator Jul 20 '17 at 08:39
  • @hgoebl - when I remove the function the code compiles beautifully, so the problem has to be within the function. As specified, I'm using Angular 4, with TS version 2.2.2 . VS code is running version 2.3.2. – Basya Rosemann Jul 20 '17 at 08:45
  • Also, the following chars are highlighted in my editor (vs code): `[1e7]+-1e3`. Can it be a TS version issue? – Basya Rosemann Jul 20 '17 at 08:48
  • 2
    OK, I see. Seems like TS compiler internally converts -1e3 to -1000. If you want to get rid of the problem quickly, just replace the thing before `.replace` with `'10000000-1000-4000-8000-100000000000'` – hgoebl Jul 20 '17 at 08:53
  • @hgoebl - Huh. Can you please explain why TS does this and how this works? – Basya Rosemann Jul 20 '17 at 10:10
  • You can generate unique values by new Date().getTime().toString() + Math.random().toString().split(".")[1] Just a thought – Kamran Sep 20 '19 at 02:19

1 Answers1

9

If you want to leave the somehow cryptic code (a puzzle?) almost as it's ingenious original but TypeScript compatible, you could use:

function uuidv4(): string {
  return (''+[1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, ch => {
      let c = Number(ch);
      return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
    }
  )
}

Unscrambled:

  • [1e7]+-1e3+-4e3+-8e3+-1e11 produces the string 10000000-1000-4000-8000-100000000000 and saves an unbelievable amount of characters ;-)
  • TypeScript is not aware that the expression is intended to produce a string. (This could be regarded as bug IMHO.)
  • When you start the expression with '' +, type inference detects the expression as string and compiler now accepts concatenating the array with the numbers. A more readable form would be '' + 1e7 + -1e3 + -4e3 + -8e3 + -1e11, because then you no longer need the [] to treat the + operators as string concatenation instead of a numeric addition.
  • The next problem arises with the auto-coercion of c from string to number. For this, I've added an explicit conversion from ch as string to c as number.

That's another proof that "just rename your *.js files to *.ts and you have valid TypeScript" is not true in all cases. I'm still convinced that using TypeScript pays off very soon and such small changes do not cost much.

hgoebl
  • 12,637
  • 9
  • 49
  • 72