Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unsupported wrapper object #54059

Closed
JadsonLucena opened this issue Apr 28, 2023 · 5 comments
Closed

Unsupported wrapper object #54059

JadsonLucena opened this issue Apr 28, 2023 · 5 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@JadsonLucena
Copy link

Missing / Incorrect Definition

Regarding the file: https://github.com/microsoft/TypeScript/blob/main/src/lib/es5.d.ts

I noticed that the methods only accept primitive literals, but not primitive objects either.
However, it is important to point out that both have the same methods and should be interpreted in the same way.

Sample code that should work

const a = 'xyz'
const b = new String('xyz')

console.log(typeof(a)) // string
console.log(typeof(b)) // object 

console.log(/[a-z]/i.test(a)) // true
console.log(/[a-z]/i.test(b)) // true

console.log(parseFloat(a)) // NaN
console.log(parseFloat(b)) // NaN

console.log(decodeURI(a)) // xyz
console.log(decodeURI(b)) // xyz

console.log(a.replace(b, 'abc')) // abc

// I could cite many other examples, but I believe that is enough.

Error message caught on lines trying to use variable "b"

Type 'String' is not assignable to type 'string'.
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.

Caveats

Strict mode was disabled in testing
The example is with string, but the behavior extends to other types: Number, Boolean, ...
The example is with the test method, but the behavior extends to other methods and functions that receive a primitive value

Documentation Link

Primitives have no methods but still behave as if they do. When properties are accessed on primitives, JavaScript auto-boxes the value into a wrapper object and accesses the property on that object instead.

@jcalz
Copy link
Contributor

jcalz commented Apr 29, 2023

It is intentional that TypeScript sometimes prevents you from doing something that would be legal JavaScript. See What does "all legal JavaScript is legal TypeScript" mean?. Yes, JS does well-defined and often reasonable things when dealing with wrapped primitives, but that doesn't imply TypeScript should allow them.

TypeScript takes the position that you should almost never intentionally be using the wrapper types; see the TS Handbook Do's and Don'ts. I doubt very much that they will want to add support for primitive wrapper objects.

On the other hand, if #2361 / #35945 / #43428 ever get implemented, then you might get this behavior "for free", without needing to make wide-ranging changes to libraries.

@JadsonLucena
Copy link
Author

We found in the description of the official website "https://www.typescriptlang.org/": TypeScript extends JavaScript by adding types to the language

I believe that this stance of limiting the use of wrapper types violates the Open-Closed Principle and the Liskov Substitution Principle of SOLID

I understand and respect the design decisions made regarding this feature. But I hope the decision is revised so that this new syntax doesn't smother JS's already well-established features.

@RyanCavanaugh
Copy link
Member

The problem here has to do with what actually constitutes a string when you're only talking about this in a structural context. You could argue that the only thing that really matters here is that the underlying object has a toString method at all, but that's obviously not the right metric because everything has that. So you need some distinguishing way that be identifies what it is about the object that makes it truly a good idea to use it as a string versus one that doesn't. This problem gets even worse for things like Boolean which have which have many fewer intrinsic methods with which to differentiate them from something else.

The use of these wrapper objects in javascript is objectively quite rare, since they don't do anything that you couldn't do with just a normal primitive string. We could reevaluate the priority of this suggestion if suddenly wrapper objects became very popular in javascript for some reason, but so far that hasn't happened and I don't think we will.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label May 3, 2023
@JadsonLucena
Copy link
Author

I agree that wrapper objects are rarely used, but it would be remiss not to consider them.
I may not have understood correctly, but I believe that the purpose of typescript is to facilitate development by adding features, not removing them.

I usually use wrapper objects when I need to create value objects, which, on top of that, are primitive types that have a pattern and need verification. In this scenario, I use classes that extend wrapper objects to take advantage of polymorphism.

Anyway thanks for labeling this issue at least as intended.

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants