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

A way to express that a method must be overriden #43910

Open
5 tasks done
geoffreytools opened this issue Apr 30, 2021 · 2 comments
Open
5 tasks done

A way to express that a method must be overriden #43910

geoffreytools opened this issue Apr 30, 2021 · 2 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@geoffreytools
Copy link

geoffreytools commented Apr 30, 2021

Suggestion

In Javascript it is possible and encouraged in documentations like MDN to override toString and valueOf for custom objects, because the version inherited from Object is not very useful (the dreaded [object Object]).

However, there is to my knowledge no way to express in a type that a class must override those methods (or that an object must have them as own properties) and therefore no way to know if they are reliable.

🔍 Search Terms

method overriding, toString, own property

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

An idea would be to have a own modifier which would basically compare a property name with the list produced by the following function

const ownModifierList = (obj) => {
  const isObjectLiteral = obj.constructor.name === "Object";
  const toList = isObjectLiteral ? obj : obj.constructor.prototype;
  return Object.getOwnPropertyNames(toList).filter(x => x !== 'constructor')
}

I think it reads well:

type showable = {
   own toString: () => string
}

📃 Motivating Example

Having a useless toString is borderline a Liskov substitution violation and Javascript users have learned to not rely on it. Typescript could come to the rescue.

The modifier would also make it easy to reject Object.create(null).

I have been reading some Haskell lately and I was envious of the confidence the type class Show gives haskellers, but it is built in. Javascript uses toString for type coercion and I believe it makes more sense to try to achieve that level of confidence by fixing it.

I don't know in what other circumstances one would require that a method is overridden as it would indicate that the base class's method is not suitable, which would be a red flag, but my lack of imagination is no proof that it can't be useful in other situations.

💻 Use Cases

Having a polymorphic way to query a string from an object.

Currently one would need to implement a custom method or signify by some tag that toString is safe to use, and the user of the object would need to know about this tag/custom method.

We can imagine generic functions like a sorting function which default to converting an object to a string in order to deal with it, but only if it is a usable string. The IDE would advertise by the function definition in the tooltip that it is possible to pass an object as long as it implements toString, which would make the user happy as it would potentially clean up some code in many places.

@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Apr 30, 2021
@geoffreytools
Copy link
Author

This eslint no-base-to-string rule solves a distinct concern which is user-centric: "am I OK with potentially seeing [Object object], globally, in my project".

If a specific function only accepts objects with a own toString or valueOf because it relies on it (an example given is sorting), then it is an implementer-centric concern, and failing to provide such object to the function is not a matter of user preference, it is a type error.

Having to opt-in globally for a type error which only applies to one function exposes the user to false positives they will be forced to handle everywhere else.

It also gives no guarantee to the implementer that the function will be used correctly because the user may not have enabled this rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants