webcomponents / custom-elements-manifest

A file format for describing custom elements
BSD 3-Clause "New" or "Revised" License
367 stars 27 forks source link

[Proposal] Extend the `type` object with more detailed information #88

Open michaelwarren1106 opened 2 years ago

michaelwarren1106 commented 2 years ago

Currently the type def for the type object has only text, references, and sources as available data.

Given that text is meant to be type definition's text as is, there could be more detail added (and more features provided from analysis tools like cem/analyzer) if the type object is changd/expanded to something like:

export interface Type {
  name?: string;
  definition?: string;
  values?: string[]
  references?: TypeReference[];
  source?: SourceReference;
}

Consider a case like this:

export type MyCustomType = 'valueA' | 'valueB';

@property() myProp: MyCustomType = 'valueA';
// cem.json
{
  ...
  {
    kind: field,
    type: {
      name: 'MyCustomType',
      definition: `'valueA' | 'valueB'`,
      values: [ 'valueA', 'valueB']
    }
  }
  ...
}

All the type properties would be optional to support different kinds of type definitions where not all parts would be able to be determined.

export type MyCustomType = { someProp: string; someOtherProp: number};

@property() myProp: MyCustomType;
// cem.json
{
  ...
  {
    kind: field,
    type: {
      name: 'MyCustomType',
      definition: `{ someProp: string; someOtherProp: number}`,
      values: undefined
    }
  }
  ...
}

If analysis tools can "unwrap" the named type definition and get at the actual values, those could be provided in js structures in the cem.json and unlock a TON of potential for the cem.json to be used in lots of different documentation implementations. Getting a list of the type values from the type itself isnt that easy, but getting it from the cem.json would be trivial, but the schema as is doesnt have a place to put such information if it could be retrieved.

justinfagnani commented 2 years ago

I think this should probably be deduped with #51

justinfagnani commented 2 years ago

I know there are a lot of requests for more detailed type information. I think we've seen them for enums, min/max value, maybe regexes, interfaces, etc.

Overall, I'm very reluctant to define our own set of type-declarations and constraint system. The idea with TypeReferences was to adopt a strategy to delegate type information to whatever type system the project uses (quite likely TypeScript) if there is one, and encode enough information for tools to be able to merge metadata from the manifest and type declarations.

I believe that strategy is good work for the information that's covered by the type system being delegated to. However, many parts of the existing schema already overlap with a type system: ClassLike and FunctionLike are interfaces. This is the rationale I used to proposed that we add interfaces as in https://github.com/webcomponents/custom-elements-manifest/pull/77

Some of the constraints like min/max that people want aren't covered by common type systems (TypeScript). Some of those are addressed in other systems like JSON Schema. So I think if we did include those kind of constraints, we should probably reuse the work done elsewhere or delegate to that type-description system entirely. Maybe we can include JSON Schema into this schema and allow fields to be described with it?

Because this is in several issues and I deduped this one last night, I think I'm going to open a new issue on the broader topic.

michaelwarren1106 commented 2 years ago

That makes sense. I think my ultimate desire for this type of thing is that i'm using the manifest to back an implementation of the Playroom from the Braid Design System.

https://seek-oss.github.io/braid-design-system/playroom https://github.com/seek-oss/playroom

The Playroom enables a dev or designer type person to drop in components into a series of iframe portals where they can see a live version of their coded UI in a variety of screen sizes. Part of the Playroom is that it provides "hints" when you type certain characters into the code editor. Our version of the Playroom (private fork hacked up to work with web components - side note, i'd love to make a web component-driven version of this application someday for open-wc) is gonna be a key part of my design system's docs, so I want to make sure I can automate as much as I can so it stays accurate.

I am currently using the custom elements manifest json to build all the hints for all my components. So, if there is a union type in my code with a bunch of string values for some attribute, having those in an easily parseable format is super helpful!

I would hope that i'm not alone in using the manifest for building component "builders" so thats why i proposed that the schema include a place to unwrap named types into their actual values (where possible) so that tools like the cem analyzer has a schema-approved place to put unwrapped types.

For the time being, I've resorted to having to inline all my union types instead of creating named types for those attrs/props, so that the cem analyzer can parse them correctly. But I also noticed that even if the cem analyzer adds the feature to parse union type value strings into real arrays, there's no place in the official spec to put that, so they'd be making non-standard spec properties, which prolly isnt good.

Basically, with this proposal, I am suggesting that type unwrapping might be common, and that the schema maybe should simply provide a place for adding some version of the types unwrapped values, and letting tools like the analyzer decide what goes in it.

KonnorRogers commented 1 year ago

Accidentally came across this, but check out cem-plugin-expanded-types by @break-stuff .

https://github.com/break-stuff/cem-tools/tree/main/packages/expanded-types

It fixes this exact problem by appending an expandedType onto the manifest.