-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Support WebIDL interfaces nominally (not just structurally) #59971
Comments
Note that let s = Object.create(AbortSignal.prototype)
// s passes an instanceof check
console.assert(s instanceof AbortSignal)
// but s is still not admissable when expecting an AbortSignal
await fetch(
'http://example.com',
{signal: s}
) // runtime TypeError |
Essentially a duplicate of #202, or at least requires that issue first. |
Even if they went through the trouble of making |
Perhaps. That issue seems to be about user-defined types, whereas this is for platform-defined types. Regardless, I think the machinery actually is in place to do limited nominal typing. declare const PrimaryInterface : unique symbol
// https://webidl.spec.whatwg.org/#dfn-platform-object
type PlatformObject<in out idlInterface> = {
/** @internal */
readonly [PrimaryInterface] : idlInterface
}
type StructuralAbortSignal = AbortSignal
type NominalAbortSignal = PlatformObject<"AbortSignal">
type PlatformAbortSignal = NominalAbortSignal & StructuralAbortSignal
// this function will only check if signal is an "AbortSignal" - it won't suggest adding members to make it so
declare function myAbortable(signal: PlatformObject<"AbortSignal">):void;
myAbortable(null as any as PlatformAbortSignal) // okay
myAbortable(null as any as AbortSignal)
// Property '[PrimaryInterface]' is missing in type 'AbortSignal' but required in type 'PlatformObject<"AbortSignal">'.
myAbortable(null as any as {})
// Property '[PrimaryInterface]' is missing in type 'AbortSignal' but required in type 'PlatformObject<"AbortSignal">'.
myAbortable(null as any) // okay |
I would hope and expect that even with "proper" nominal typing support, we would still be able to use type assertions when we believe we know better than the type checker. That's not really an argument against using nominal typing here, even if we have to roll our own. |
This is all my opinion, so feel free to ignore it. I'm not trying to argue against using nominal typing, I'm saying that without officially supported nominal typing, TS's error messages imply object that type mismatches are structural in nature. They all mention that such-and-such members are missing. Currently the Personally I think "you're missing a zillion members" is as likely to deter people as "you're missing this one magical member", and neither approach is going to stop the person we're imagining guarding against. Like, when you see an object type with a |
The problem actually is the missing "one magical member" ([[PrimaryInterface]] internal slot). @jcalz, what error message would you have? e.g. FireFox's runtime message is:
Chrome:
Safari:
|
The problem at runtime is the internal slot, which isn't the same as a TS type with a symbol-valued key, and someone calling your code with Anyway, I think I might be repeating myself at this point and I'm not a TS team member so my opinion isn't going to move this issue in any direction. I'll bow out for now. |
Yes, it's a hack. It's less of a hack than the current behavior: relying on the structural type of an e.g. const justASignal = Object.setPrototypeOf(AbortSignal.timeout(0), null)
fetch('http://example.com', {signal:justASignal}) I guess you could say that this is structural - it's just that the identifier is not exposed to the JavaScript runtime, and a symbol-typed key, which you're not going to dereference by accident, seems the closest equivalent in TypeScript today. There are other internal slots (e.g. |
This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
π Search Terms
WebIDL, Nominal, Structural, Interface, platform object
β Viability Checklist
β Suggestion
TypeScript should provide better support for "platform objects". Right now, it only checks them structurally, which:
Instead, it should:
unique symbol
types)π Motivating Example
Take the following code:
This emits the error:
aSignal
is NOT a platform object and that its "inherited interfaces" (in the WebIDL sense) does not includeAbortSignal
.AbortSignal
need not structurally examine the value.π» Use Cases
The text was updated successfully, but these errors were encountered: