-
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
Opaque types for WebGL #5855
Comments
@crobi you raise two issues, the first about interface WebGLFramebuffer extends WebGLObject {
constructor: WebGLFramebuffer;
} the second one is about constructors, most of the DOM elements have constructors though they are not callable. the problem is that |
@crobi as a work around, you can define the constructor in your files, and this should cause the compiler to flag the error as expected. |
sorry, scrap my original comment, the constructor would not do it, we need something not defined on object, some sort of |
This crossed my mind as well, but I'm not sure such a workaround would look nice in
In plain Javascript, > gl.createFramebuffer() instanceof WebGLFramebuffer
true
> gl.createFramebuffer() instanceof WebGLTexture
false
> new WebGLFramebuffer
Uncaught TypeError: Illegal constructor
> gl.createFramebuffer()
WebGLFramebuffer {} |
No run time transformations. the right operand of |
@mhegazy A noncallable constructor would be what abstract classes would need as well (both for |
FWIW, I added the full WebGL extensions and simple branding in my project, see: I could turn this into a PR for lib.d.ts if wanted. This was also submitted in an earlier form to DefinitelyTyped: That one does not have the branding values, which until #202 is implemented may be preferable for the core lib as the branding types are a workaround. |
I'd like to propose a compromise until #202 is implemented. Instead of taking the branded approach which muddies up lib.d.ts with distinct fields for each class, we could declare these WebGL interfaces as classes with private constructors[1] and with a private member named declare class WebGLObject {
private invalidated: bool; // Why invalidated: bool? See note [3]
}
declare class WebGLFramebuffer extends WebGLObject {
private constructor(); // Enforce the second class of error: new WebGLFramebuffer
private webGL: any;
} Makes the original example produce readable and actionable type errors: example.ts(3,38): error TS2345: Argument of type '"abc"' is not assignable to parameter of type 'WebGLFramebuffer'.
example.ts(6,9): error TS2673: Constructor of class 'WebGLFramebuffer' is private and only accessible within the class declaration. This approach also prevents another dangerous surprise which presently typechecks just fine: function wrongDeletion(gl: WebGLRenderingContext, fbo: WebGLFramebuffer) {
gl.deleteBuffer(fbo); // This should have been gl.deleteFramebuffer(fbo);
} With this approach, we'll have a type error: surprises.ts(2,21): error TS2345: Argument of type 'WebGLFramebuffer' is not assignable to parameter of type 'WebGLBuffer'.
Types have separate declarations of a private property 'webGL'. I'll follow up shortly with a PR. Notes:
|
Strike the "follow up shortly with a PR" it looks like this may require a change to TSJS-lib-generator to support generating/overriding |
WebGL types are included in the default
lib.d.ts
. However, most types are defined as empty interfaces, which means that the compiler doesn't catch many WebGL errors.Consider the following code:
gl.bindFramebuffer
should be aWebGLFramebuffer
object, but passing astring
does not emit a compile error or warning.WebGLFramebuffer
can only be constructed viaWebGLRenderingContext.createFramebuffer
, calling new throws an error at runtimeIdeally, Typescript would know that
WebGLFramebuffer
, even though it has no public properties, cannot be constructed or converted to any other type.I assume that this is not easy to specify with structural typing, but having such opaque types could be useful for other libraries as well (e.g., for returning handles).
If that is not possible, can we find a workaround that at least helps catching the above mentioned bugs?
For reference, here's how the above types are currently defined in
lib.d.ts
:The text was updated successfully, but these errors were encountered: