2

String('str') is not an instance of type String:

// false
String('str') instanceof String

// true
typeof String('str') === 'string'

new String('str') will create a wrapper object around 'str' which leads to:

// true
new String('str) instanceof String

// false
typeof new String('str') === 'string'

For me, this means

const myString: String = String('str')

Should generate a compile error because of invalid type, but it does not. Whereas:

const myString: String = new String('str')

Does not generate a compile error as well. This applies to the other primitive wrapper objects as well.

Is this by design? If so, why? If I want to differentiate between new String() and String(), I can't, which should be able just for type safety at compile time, but also at runtime with reflect-metadata, or am I missing something?

nintschger
  • 1,786
  • 5
  • 30
  • 45
  • I'm curious what your use case is for using wrapper objects at all...? I've only very, very rarely seen them used intentionally and for good reason in real code. – T.J. Crowder May 13 '19 at 09:55
  • 1
    @T.J.Crowder I do not have a use case. I wrote a decorator which validates the type of the value assigned to the decorated property, which lead me to this question since 'reflect-metadata' returns the same type for `String()` and `new String()`, therefore, I can't validate correctly. – nintschger May 13 '19 at 09:58
  • 2
    Because boxing and unboxing is automatic in JavaScript. See for example references [in the answer from @T.J.Crowder here](https://stackoverflow.com/questions/34067261/is-boxing-coercion-in-javascript). – Paleo May 13 '19 at 10:00
  • 1
    @Paleo - True, but you can see RagnarLodbrok's point. `const myString: String = 'str';` (or `= String('str')`, which is the same thing) assigns a primitive string to a variable declared as an object type (it [doesn't coerce it](https://jsfiddle.net/tjcrowder/h28tkwpr/), because that's a runtime thing and these are compile-time types). I'm sure the TypeScript team have a very good reason for this (and it likely does relate to boxing :-) ), but... – T.J. Crowder May 13 '19 at 10:15
  • `instanceof` checks if a constructor is in a prototype chain. While TS types are compatible as soon as they structurally match. From that perspective TS rules are more permissive. `new String` is structurally equal to `String`, no wondering it type-checks. – zerkms May 13 '19 at 11:03
  • 1
    "I can't" --- as soon as 2 types hold the same properties they are the same type for TS. – zerkms May 13 '19 at 11:05
  • @zerkms but `new String('str')` and `String('str')` do not hold the same properties...? – nintschger May 13 '19 at 14:16
  • @RagnarLodbrok what properties of `String` do not exist or of an incompatible type in the `new String` instance? – zerkms May 13 '19 at 20:38

0 Answers0