Skip to content
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

The WithContext type is invalid #98

Open
jasongerbes opened this issue Apr 24, 2020 · 3 comments
Open

The WithContext type is invalid #98

jasongerbes opened this issue Apr 24, 2020 · 3 comments

Comments

@jasongerbes
Copy link

The WithContext type accepts all Thing types:

/** Used at the top-level node to indicate the context for the JSON-LD objects used. The context provided in this type is compatible with the keys and URLs in the rest of this generated file. */
export declare type WithContext<T extends Thing> = T & {
    "@context": "https://schema.org";
};

However, Thing allows string values. For example:

export const thing: Thing = '';

It's not possible to intersect string and object, which makes the WithContext type invalid.

@Eyas
Copy link
Collaborator

Eyas commented Apr 24, 2020

Hm, I'm not sure this makes the type invalid per se, since intersections distribute over unions, WithContext<Thing> can essentially be written as:

WithContext<Thing> = WithContext<TypeA | TypeB | ... | string>
  = (TypeA | TypeB | ... | string) & {"@context": "foo"}
  = (TypeA & {"@context": "foo"}) | (TypeB & {"@context": "foo"}) | ... | (string & {"@context": "foo"})
  = (TypeA & {"@context": "foo"}) | (TypeB & {"@context": "foo"}) | ... | (never)
  = (TypeA & {"@context": "foo"}) | (TypeB & {"@context": "foo"}) | ...

We can make this more explicit by saying:

export declare type WithContext<T extends Thing> = Exclude<T, string> & {
  "@context": "https://schema.org";
};

Can I ask if this is triggering a bug or bad behavior here?

It is intended behavior for string not to be assignable to WithContext, since a top-level JSON-LD object needs to be an actual JSON-LD class type.

@jasongerbes
Copy link
Author

jasongerbes commented Apr 24, 2020

Just having some trouble with the following utility function:

import { Thing, WithContext } from 'schema-dts';

export const addContextToSchema = <T extends Thing>(thing: T): WithContext<T> => {
    return {
        '@context': 'https://schema.org',
        ...thing // error: cannot be destructured as Thing may not be an object.
    };
};

This is my temporary workaround:

import { Thing, WithContext } from 'schema-dts';

// TODO: Remove this type when this issue has been resolved
// https://github.com/google/schema-dts/issues/98
export type Schema = Exclude<Thing, string>;

export const addContextToSchema = <T extends Schema>(schema: T): WithContext<T> => {
    return {
        '@context': 'https://schema.org',
        ...schema
    };
};

My hope is that you can export a variant of Thing that excludes string, and update the WithContext type to instead use that variant.

Looking at schema.org, I think these top-level 'things' are called 'types':

The vocabulary currently consists of 821 Types, 1328 Properties, and 297 Enumeration values.

So perhaps:

export declare type ThingType = Exclude<Thing, string>;

export declare type WithContext<T extends ThingType> = T & {
  "@context": "https://schema.org";
};

Or maybe:

  • ThingObject
  • RootThing
  • TopLevelThing
  • Schema

@NightScript370
Copy link

Does this happen with just "WithSchema" or perhaps also with other things? I thought I remember something about this being the case, but regardless, it would probably be nice to limit the declarations that could get corrupted by the string inclusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants