-
-
Notifications
You must be signed in to change notification settings - Fork 140
Add TypeScript defintions #625
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
Conversation
0de839b
to
8681582
Compare
src/index.d.ts
Outdated
textures: DataArrayTexture; | ||
|
||
// TODO: TypeScript doesn't allow overriding properties with different types | ||
lights: LightsInfoUniformStruct; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ShaderMaterial
already uses lights
for something else (docs) and TypeScript doesn't allow overriding properties with a different type.
Property 'lights' in type 'PhysicalPathTracingMaterial' is not assignable to the same property in base type 'MaterialBase<PhysicalPathTracingMaterialDefines>'.
Type 'LightsInfoUniformStruct' is not assignable to type 'boolean'.ts(2416)
With type
you could just omit the property (type Fixed = Omit<ShaderMaterial, "lights">
), but afaik there is no way to do this with classes and interface
.
So lights
either needs to be renamed or MaterialBase
can't extend ShaderMaterial
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the recent refactor I'm thinking we may not need to export this material which would simplify things quite a bit, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if this material may not be exported in the future, I think the TypeScript error is raising a valid concern.
Due to subtyping, any class that extends ShaderMaterial
is expected to be compatible with its interface. Overriding lights
with a LightsInfoUniformStruct
may break other code that expects it to be a boolean
as defined on ShaderMaterial
in unexpected ways.
How do you feel about renaming this field to lightsInfo
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In practice this isn't an issue especially if the class is not made public but I understand what you're saying - I'm happy with a change to "lightsInfo".
Thanks! This is great. The project has just undergone a pretty big refactor so I may be limiting the API that's actually exported soon to make things easier to maintain. In practice I think the fields and classes I have documented are the ones I would consider "public" and worth adding typescript definitions for. But I'm happy to hear your thoughts, as well.
The project does use ESLint for code style. You should be able to use
You should be able to extend existing classes similar to how this is done for Raycaster in three-mesh-bvh
I'm not a typescript expert so I don't know if I feel we need typescript examples in the project but it's good to validate. |
I did use ESLint auto-fix, but what I meant was that the rules in the config are not very strict, so there is a lot of "wiggle room" for how you format the code. For example, you could add 10 empty lines between two class members or indent each of them differently without ESLint complaining or auto-fixing it.
This would extend the type across the entire application, right? I am not sure how I feel about that, especially for large projects. Someone working on an entirely different part of the app could misinterpret the materials having a Maybe these properties could be implemented as an extended material provided by
As far as I know, copying the examples and changing the extension to Having TypeScript examples that are checked during linting could help prevent the implementation and type definitions from getting out of sync in the future, so I think this is something worth considering.
Generally, I prefer when libraries export as much of the API as possible (even if it is undocumented), but I understand the burden of maintaining type definitions for everything. With the modular way Overall, it comes down to whether you think it is viable to maintain the type definitions for these parts of the API, and how much you expect them to change in the future. But in my opinion, there is definitely value in having them. |
Gotcha - this must just be the case for typescript files, then.
I'm not sure how this would be avoidable. The function takes a material class and we're extending it to expect a "matte" or "castShadow" member on it. There would be no way for a syntax detection system to know if user code was using a material with the intent of passing it into the path tracer or not.
Again I'm not a typescript expert so I can't say. I add these declaration files because people ask for or contribute them and I have to fix them when people complain.
Where would these comments live? In the typescript file? In that case I'd be okay with it for these two fields.
I understand but this means more to maintain and fix when something changes. I'd rather not add code for a solution for a problem we don't have, yet unless someone wants to take on responsibility for maintaining this part of the project.
Similarly this puts a lot of restrictions on the internals of the project and means having to consider changes to any part of the API because they're technically "public". I know it might be nice as a user but as a maintainer it's a nightmare. One of the benefits of encapsulating the path tracer in a more wholistic class is the internals can change more freely without worrying about other projects breaking. I don't think it's reasonable to try to maintain code to support non-specific use cases that may not exist. I'd much rather only export what is intended to be used and documented and if someone wants something publicly we can talk about exporting it or understand the use case and how WebGLPathTracer class can be improved to support it more easily. Again I appreciate the PR and type definitions - I think it's a good change - but lets start with the minimal additions and when we run into problems we can add a more well-considered solution for it. |
Additional Material properties
The only alternative I can think of (as mentioned) is exporting separate material classes that have those properties, similar to
Yes, just like the deprecation comments I added for the old scene generator classes (1, 2). Editors like VSCode can pick those up and show them when you hover the property. People often seem to use VSCode auto-complete instead of reading the documentation, so I wanted to make sure there was some sort of notice that these properties are not defined by Three.js itself. Unless you want to expose separate material classes, I think adding a comment is enough to avoid confusing users. TypeScript examples
Absolutely, maintaining two sets of examples is not viable at all. The most interesting solution would have been to check the existing JS examples using the TypeScript compiler (since it can do this with the With the exposed API being limited and the scope of the type definitions becoming narrower, this is no longer as relevant as before anyway. Exposed API
This makes sense, and I agree that exposing the internal API will probably only be relevant for a very small number of use cases that don't warrant the additional maintenance overhead.
Sounds good, then I guess I'll wait for you to limit the exported API and adjust the type definitions accordingly. |
Only for `MeshStandardMaterial` and `MeshPhysicalMaterial` as other materials are not supported by `three-gpu-pathtracer`.
If it's a separate material, if someone imports a glTF then for each object that we want to adjust these fields on - the material must be replaced, previous fields copied, and then members set. You have to strike a balance between technical idealism with practical ease-of-use for the end user and you can't always have both. The latest refactor has been focused on making the project easier to use so I'm hesitant to make changes that I know will be more cumbersome. This is my current feeling, at least. These fields could be added to
Okay great that sounds fine to me then.
I've just merged #627 which adjusts the exports to a more limited scope. I've also marked some classes as "deprecated" which we shouldn't have types added for. Related to that I'll also be removing Thanks for bearing with me in figuring all this out! |
I just updated the type definitions to match the current exports, so this PR should be ready now. Feel free to take another look and request changes if necessary. I also removed the declaration of Also, for future reference, or if anyone needs them for importing internals, here are the full type definitions. |
This is great, thank you! Once the next release is out let me know if you run into any issues with the new API and we can try to figure out how to accommodate those use cases. |
Description
Fixes: #18
This pull request adds TypeScript definitions for everything that is exported from the package root.
They were written and used for a project I am working on, so they are already somewhat tested to behave as expected (though I did have to change and update a few things, so further testing may be necessary).
Since there are some things left to do, I'll mark this as a draft for now.
Notes
_
prefix) was added to the corresponding definition@types/node
dependency was added to fix an error in the global definitions that would show up when runningtsc
Since this project doesn't use a formatter or strict ESLint rules for code style, I tried my best to match it to the rest of the project.
Formatting and grouping of class members
To-do
PhysicalPathTracingMaterial
overriding property with different typethree-mesh-bvh
)WebGLPathTracer
(docs)Investigate TypeScript examples to ensure the definitions work as expected