TypeScript Version: 3.4.0-dev.20190305
Code
const key: keyof Boolean = "toString"; // error - "toString" is not assignable to "valueOf"
const x: {toString(): string} = new Boolean(); // no error
const y: Boolean["toString"] = true.toString; // no error
class Bool extends Boolean {
protected toString() { // also no error, but should be
return "";
}
}
Expected behavior:
keyof Boolean should be "toString" | "valueOf"
Playground
Apparent properties (such as toString) intentionally aren't included in keyof or inheritance validity checks, so some inconsistencies between keyof and property access is expected and intentional.
I think we could safely add toString to interface Boolean, though I am extremely curious how you came to notice this in the first place.
@RyanCavanaugh you wrong. keyof of any other type includes toString. For example: keyof Number, keyof String. even keyof Symbol
you wrong. keyof of any other type
No, I right.
interface Foo { m; }
// Error
const k: keyof Foo = "toString";
Unlike Boolean, Number, String, and Symbol have explicitly-declared toString methods in their corresponding interface, which is why toString is in their keyofs, which is why I proposed adding toString to Boolean's interface.
@RyanCavanaugh ok. so the same problem with RegExp, Date, ... And now there is inconsistency:

playground
@jacksteinberg and I have noticed this in a project that is using the TypeScript definitions. We have so far identified the following missing declarations:
stringifier in the spec) (link to TypeScript definition)In contrast, others overrides of Object.prototype methods are included in the TypeScript definitions, e.g. Number.prototype.toString, Boolean.prototype.valueOf, Array.prototype.toLocaleString.
We haven't done an exhaustive search; those were just particular instances of overridden toStrings that we were trying to pick up with our tool (but ended up getting the wrong result due to the missing TypeScript definitions). In particular I wonder if other stringifiers in Web IDL interfaces are not being picked up correctly.
/cc @saschanaz as someone who has been helpful keeping TypeScript's built-in type definitions up to date in the past.
Corresponding issue on TSJS-lib-generator: https://github.com/microsoft/TSJS-lib-generator/issues/322.
The emitter currently does not do anything for stringifier and only provides the inherited toString.
We could generate toString for every interfaces but that would be a big noise and duplication, maybe we should just include toString in keyof?
I think it'd be best to include toString for the interfaces which have specific toString behavior that differs from Object.prototype. There are not many of those. (I'd guess 5 in the JS spec, 20ish on the web platform.)
This already seems to be the policy, e.g. Array.prototype.toString and Number.prototype.toString are included. There are just some that got missed for whatever reason.
I think it'd be best to include toString for the interfaces which have specific toString behavior that differs from Object.prototype.
Definitely can be done, but what would be the use cases? Couldn't understand the purpose of https://github.com/jackbsteinberg/get-originals-rewriter/issues/79.
Abbreviated summary: we're using the TypeScript type system to transform calls of the form x.toString() into AppropriateClass.prototype.toString.call(x). Without accurate information about the methods in x's prototype chain, this is not possible.
In general, anything which is relying on the TypeScript definitions giving an accurate summary of what methods a class has will encounter this problem.
Object.prototype.toString is a native function that returns '[object Object]'. So shouldn't be errors like
because it is JS core feature.
PS And we didn't start to talk about Symbol.toPrimitive
Most helpful comment
Abbreviated summary: we're using the TypeScript type system to transform calls of the form x.toString() into AppropriateClass.prototype.toString.call(x). Without accurate information about the methods in x's prototype chain, this is not possible.
In general, anything which is relying on the TypeScript definitions giving an accurate summary of what methods a class has will encounter this problem.