schema-dts
schema-dts copied to clipboard
The WithContext type is invalid
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.
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.
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
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.