GithubHelp home page GithubHelp logo

Split types.ts about pnp-js-core HOT 15 CLOSED

sharepoint avatar sharepoint commented on June 11, 2024
Split types.ts

from pnp-js-core.

Comments (15)

pbjorklund avatar pbjorklund commented on June 11, 2024 1

Assign this to me and I'l create a PR that shows it in action and we can decide if good or bad idea after.

from pnp-js-core.

patrick-rodgers avatar patrick-rodgers commented on June 11, 2024 1

All set, thanks for having a look.

from pnp-js-core.

pbjorklund avatar pbjorklund commented on June 11, 2024 1

The [ ] were meant to indicate a "todo" for myself :)

from pnp-js-core.

patrick-rodgers avatar patrick-rodgers commented on June 11, 2024

I keep going back and forth on this one in my head. These are just type defs / interfaces to help with typing return values and parameters - likely would never need to use them separately. We could move to individual files and play with the TypeScript namespace/module merging and see. I would like to keep the ability to just include "types" whatever the syntax is - and not have to include lots of files if I needed to use more than one type. Splitting it does make sense as these grow, will be much easier to find and update stuff - but there is always ctrl+F. Someone can convince me either way probably, let's discuss on this weeks call and make a decision.

from pnp-js-core.

pbjorklund avatar pbjorklund commented on June 11, 2024

Points to be dealt with:
[ ] Find the best way to reference all types at compilation/code time without having to import {} every type by itself
[ ] The locale enum adds 7kb to the package. Should it be included? Bigger question: Should we allow cherry picking from the library, see #87
[ ] Exclude "empty type files" from the packaging process since it just adds LoC for no reason. Investigate http://www.typescriptlang.org/docs/handbook/declaration-merging.html

(New PR opened in #89, action points extracted from #77)

from pnp-js-core.

patrick-rodgers avatar patrick-rodgers commented on June 11, 2024

Looked at the PR - I see all the types broken out, but not sure which of the above points it covers? I guess my 2c:

  • one file does that
  • I don't think we need a 7k enum, but that's me. Also, I don't think we are blocking cherry picking/tree shaking/whatever, at least not intentionally. No one has pointed out what changes (if any) we need to make to support this. Not a high priority for me currently, but not against it either.
  • Yes, excluding empty code blocks just makes sense.

from pnp-js-core.

pbjorklund avatar pbjorklund commented on June 11, 2024

https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines states

Shared types should be defined in 'types.ts'.

And in https://github.com/Microsoft/TypeScript/blob/master/src/compiler/types.ts we can see that they mix types/interfaces/enums in their types.

A file/module with only an interface export generates an interfaceName.js file with "use strict"; as the only content. That's minus one for a pure file for each interface.

So I started to look at how vscode does it and I kinda like their approach.

Let's take https://github.com/Microsoft/vscode/blob/5b9ec15ce526decc5dd0488339e798f6bcb4ec46/src/vs/base/common/event.ts

They export interfaces alongside with the implementation of the thing that is used which looks clean to me.

This leads to files like https://github.com/Microsoft/vscode/blob/5b9ec15ce526decc5dd0488339e798f6bcb4ec46/src/vs/editor/common/commonCodeEditor.ts with many import statements.

I myself like the readability and clear intent of specifying what we import into a class vs using import *.

Side note: I have no idea what's going on at the end of their https://github.com/Microsoft/vscode/blob/5b9ec15ce526decc5dd0488339e798f6bcb4ec46/src/vs/base/common/types.ts

So heres my two cents that we can discuss -

  1. If you write a class, write an interface for the class in the same file. Generalize the interface and concretize the class. Iterator = interface, ListIterator = class
    1.1 If the interface is shared between multiple files, export the interface in /src/types/types.ts
  2. If you write a function, consider writing an interface for the function for readability and clarity inside the module. If it is shared put it inside /src/types/types.ts
  3. If you write an enum put it inside /src/types/enums as a separate file

Edit: Let me know if this is unclear or if anyone wants me to cook up some sample code to show how these style guidelines could be implemented on any current piece of code. Not doing that before we either accept this proposal or someone asks me to ;)

from pnp-js-core.

pbjorklund avatar pbjorklund commented on June 11, 2024

Re cherry picking perhaps this is what @mike-morrison is talking about in #85. I think we should solve that issue before deciding on the Locale enum as they are interconnected.

from pnp-js-core.

mike-morr avatar mike-morr commented on June 11, 2024

@pbjorklund Wow! That vscode is beautiful. It's so consistent in style. Speaking of, can we relax the tslint rules a bit. Seeing the squgglies and having to delete white space to make them go away is getting on my nerves for something that is going to get transpiled and minified anyways. CRLF at the end of files, etc. Is there some other gain I am missing?

from pnp-js-core.

pbjorklund avatar pbjorklund commented on June 11, 2024

@patrick-rodgers any thoughts on the above before I start?

from pnp-js-core.

patrick-rodgers avatar patrick-rodgers commented on June 11, 2024

I don't see any value in duplicating all the classes as interfaces, and I don't see that supported by the files you linked. They are exporting both interfaces and classes as are we - but not 1 interface per class. Also, I've been a fan of keeping all the common utility types in a single types file from the beginning. They are also using both import syntaxes as appropriate; * and {} as are we.

Classes in TS are essentially also interfaces. If I have a class and a function like:

class foo {
public a: string;
public b: string
}

function something(f: foo) {...}

I can already do the below because the type checking is structural.

something({ a: "Hello", b: "World" });

Implementing a rule that for every class we write we also have and maintain a duplicate interface doesn't add any value or make consumption easier, it just increases overhead. Not sure this is worth pursuing.

from pnp-js-core.

pbjorklund avatar pbjorklund commented on June 11, 2024

I don't see any value in duplicating all the classes as interfaces, and I don't see that supported by the files you linked.

I like to program against interfaces instead of implementations, perhaps my background from other languages are taking over to much compared to what the TS best practices/environment are.

When you use a class as an interface in TS you also get the internals of the class.
Here's a short example of what I mean in a snippet

Also, I've been a fan of keeping all the common utility types in a single types file from the beginning.

I want us to agree on something and put it in a styleguide for when other people come along and start thinking about the same thing I did.

Is it the implied "always" you don't like? Then how about something like:

  1. If you write a class, consider writing a generalized interface for the class in the same file.
    E.g Iterator = interface, ListIterator = class.

1.1 If the interface is shared between multiple files, export the interface in /src/types/types.ts

When it comes to functions that have complicated signatures I like to have an interface for them, just makes life easier, but don't have special other reasons besides that.

If no-one cares about discussing things like these I shouldn't waste my energy and go hack on some other part of the library. Just let me know.

from pnp-js-core.

patrick-rodgers avatar patrick-rodgers commented on June 11, 2024

I think we are using interfaces where it makes sense, for provisioning providers for example. Maybe there are places where we could make things more generic, on the whole I think we are in pretty good shape. Take web for example - will we realistically have separate web implementations such that we need an IWeb (I know you are opposed to using the "I" prefix)? While I agree with your point 1, it is just good programming practice to use interfaces when appropriate - so do we need to call that out for folks?

As for the location, we could put them all in types.ts - currently we are keeping the generic ones we don't own (i.e. those that come from the service declarations) in types and the ones we own near where they are used (again I'll use the example of configuration providers). That seems easier to me to edit, find things since we will likely change our interfaces, but never (until there is a service update) the ones we don't own, so stuffing them in a giant long file is less of a pain.

I am not sure what you mean regarding interfaces for functions - so you mean the parameters? So instead of function f(x,y,z,f,e,s,a,r,fg,d,ad) it would be f(foo: IFoo)?

from pnp-js-core.

pbjorklund avatar pbjorklund commented on June 11, 2024

Take web for example - will we realistically have separate web implementations such that we need an IWeb

It's very useful to be able to easily switch out the implementation when doing unit tests or functional tests where you want to isolate what effect a dependency has on a function (testing glue for instance).

I know you are opposed to using the "I" prefix

After doing research it seems that there is no consensus at all in the TS community... Let's just pick a standard and go with it, that's more important then discussing forever how to name them and never actually getting to implement the names. And when I saw that the SharePoint Framework uses INaming I think we should probably go with that as well. If you are ok with that I'l go ahead and add it to the style guide.

so do we need to call that out for folks?

Not sure if that's a question or a statement?

As for the location, we could put them all in types.ts - currently we are keeping the generic ones we don't own (i.e. those that come from the service declarations) in types and the ones we own near where they are used (again I'll use the example of configuration providers).

How about this for a section in the style guide?:

Interfaces

When writing a generic interface that is used at multiple locations or the interface is external it should be put into /src/types/types.ts
Interfaces we own should be included alongside the concrete implementation in the same file

That seems very close to the latest proposition I had, or am I missing something?

I am not sure what you mean regarding interfaces for functions - so you mean the parameters?

One usage for that is typing configuration objects, but I don't have a real preference on lots of params vs config objects as long as they have no behavior. Also not sure if typing functions actually give anyone but me any extra value, I just like to be able to read "function contracts" separately, but due to the ... promiskuity? of JS I don't know a way to make them useful in an editor or at compiletime. Let's not include that one at all for now.

So if we can agree on that I can go hunting across the codebase and see if we already follow this or not. If we already do it this way it's great because then we would already be in line with what we write in the style guide.

from pnp-js-core.

patrick-rodgers avatar patrick-rodgers commented on June 11, 2024

Going to close this one for now, please reopen it if you have an update or any progress to add. Been open for a bit with no activity.

from pnp-js-core.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.