Skip to content

Commit 82ddbbe

Browse files
committed
Add Type-safe strings for Number, Integer, Float
Schema.org Numbers, Integers, and Floats support being assigned to strings with the appropriate fromat (e.g. "4394" for Integer). With TypeScript 4.1.0 and beyond, this can be expressed with the `` `${number}` `` type. This pushes the minimum required version for schema-dts from 3.4.0 to 4.1.0, and is thus a breaking change. Note there's a future situation where we would RESTRICT the `Integer` type further; so that only valid integral numbers are assignable to it. This will be another breaking change for another time, when TypeScript can finally represent this. Fixes #130.
1 parent f5fda5d commit 82ddbbe

13 files changed

Lines changed: 107 additions & 68 deletions

dist/schema/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "schema-dts",
3-
"version": "0.9.0",
3+
"version": "0.10.0",
44
"displayName": "schema-dts: Strongly-typed Schema.org vocabulary declarations",
55
"description": "A TypeScript package with latest Schema.org Schema Typings",
66
"authors": [
@@ -17,7 +17,7 @@
1717
"devDependencies": {},
1818
"dependencies": {},
1919
"peerDependencies": {
20-
"typescript": ">=3.4.0"
20+
"typescript": ">=4.1.0"
2121
},
2222
"keywords": [
2323
"typescript",

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "schema-dts-gen",
3-
"version": "0.9.0",
3+
"version": "0.10.0",
44
"displayName": "schema-dts Generator",
55
"description": "Generate TypeScript Definitions for Schema.org Schema",
66
"authors": [
@@ -54,7 +54,7 @@
5454
"rxjs": "^7.2.0"
5555
},
5656
"peerDependencies": {
57-
"typescript": ">=3.4.0"
57+
"typescript": ">=4.1.0"
5858
},
5959
"nyc": {
6060
"extension": [

src/transform/toClass.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@ function toClass(cls: Class, topic: Topic, map: ClassMap): Class {
3939
}
4040

4141
const wellKnownTypes = [
42-
new AliasBuiltin('http://schema.org/Text', 'string'),
43-
new AliasBuiltin('http://schema.org/Number', 'number'),
44-
new AliasBuiltin('http://schema.org/Time', 'string'),
45-
new AliasBuiltin('http://schema.org/Date', 'string'),
46-
new AliasBuiltin('http://schema.org/DateTime', 'string'),
47-
new AliasBuiltin('http://schema.org/Boolean', 'boolean'),
42+
new AliasBuiltin('http://schema.org/Text', AliasBuiltin.Alias('string')),
43+
// IMPORTANT: In the future, if possible, we should have: `${number}` in Float only,
44+
// an integer string literal in Integer only, and Number becomes simply Float|Integer.
45+
new AliasBuiltin(
46+
'http://schema.org/Number',
47+
AliasBuiltin.Alias('number'),
48+
AliasBuiltin.NumberStringLiteral()
49+
),
50+
new AliasBuiltin('http://schema.org/Time', AliasBuiltin.Alias('string')),
51+
new AliasBuiltin('http://schema.org/Date', AliasBuiltin.Alias('string')),
52+
new AliasBuiltin('http://schema.org/DateTime', AliasBuiltin.Alias('string')),
53+
new AliasBuiltin('http://schema.org/Boolean', AliasBuiltin.Alias('boolean')),
4854
];
4955

5056
// Should we allow 'string' to be a valid type for all values of this type?
@@ -85,7 +91,7 @@ function ForwardDeclareClasses(topics: readonly TypedTopic[]): ClassMap {
8591
const allowString = wellKnownStrings.some(wks =>
8692
wks.equivTo(topic.Subject)
8793
);
88-
if (allowString) cls.addTypedef('string');
94+
if (allowString) cls.addTypedef(AliasBuiltin.Alias('string'));
8995

9096
classes.set(topic.Subject.toString(), cls);
9197
}

src/ts/class.ts

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export type ClassMap = Map<string, Class>;
6161
*/
6262
export class Class {
6363
private _comment?: string;
64-
private _typedef?: string;
64+
private _typedefs: TypeNode[] = [];
6565
private readonly children: Class[] = [];
6666
private readonly _parents: Class[] = [];
6767
private readonly _props: Set<Property> = new Set();
@@ -97,11 +97,15 @@ export class Class {
9797
return appendLine(this._comment, deprecated);
9898
}
9999

100-
protected get typedefs(): string[] {
100+
protected get typedefs(): TypeNode[] {
101+
const f: TypeNode = undefined!;
102+
101103
const parents = this.allParents().flatMap(p => p.typedefs);
102104
return Array.from(
103-
new Set(this._typedef ? [this._typedef, ...parents] : parents)
104-
).sort();
105+
new Map([...this._typedefs, ...parents].map(t => [JSON.stringify(t), t]))
106+
)
107+
.sort(([key1, value1], [key2, value2]) => key1.localeCompare(key2))
108+
.map(([_, value]) => value);
105109
}
106110

107111
private properties() {
@@ -198,13 +202,8 @@ export class Class {
198202
return false;
199203
}
200204

201-
addTypedef(typedef: string) {
202-
if (this._typedef) {
203-
throw new Error(
204-
`Class ${this.subject.href} already has typedef ${this._typedef} but we're also adding ${typedef}`
205-
);
206-
}
207-
this._typedef = typedef;
205+
addTypedef(typedef: TypeNode) {
206+
this._typedefs.push(typedef);
208207
}
209208

210209
addProp(p: Property) {
@@ -299,7 +298,7 @@ export class Class {
299298

300299
protected nonEnumType(skipDeprecated: boolean): TypeNode[] {
301300
this.children.sort((a, b) => CompareKeys(a.subject, b.subject));
302-
const children = this.children
301+
const children: TypeNode[] = this.children
303302
.filter(child => !(child.deprecated && skipDeprecated))
304303
.map(child =>
305304
factory.createTypeReferenceNode(
@@ -309,11 +308,7 @@ export class Class {
309308
);
310309

311310
// A type can have a valid typedef, add that if so.
312-
children.push(
313-
...this.typedefs.map(t =>
314-
factory.createTypeReferenceNode(t, /*typeArgs=*/ [])
315-
)
316-
);
311+
children.push(...this.typedefs);
317312

318313
const upRef = this.leafName() || this.baseName();
319314
return upRef
@@ -379,9 +374,25 @@ export class Builtin extends Class {}
379374
* in JSON-LD and JavaScript as a typedef to a native type.
380375
*/
381376
export class AliasBuiltin extends Builtin {
382-
constructor(url: string, equivTo: string) {
377+
constructor(url: string, ...equivTo: TypeNode[]) {
383378
super(UrlNode.Parse(url));
384-
this.addTypedef(equivTo);
379+
for (const t of equivTo) this.addTypedef(t);
380+
}
381+
382+
static Alias(equivTo: string): TypeNode {
383+
return factory.createTypeReferenceNode(equivTo, /*typeArgs=*/ []);
384+
}
385+
386+
static NumberStringLiteral(): TypeNode {
387+
return factory.createTemplateLiteralType(
388+
factory.createTemplateHead(/* text= */ ''),
389+
[
390+
factory.createTemplateLiteralTypeSpan(
391+
factory.createTypeReferenceNode('number'),
392+
factory.createTemplateTail(/* text= */ '')
393+
),
394+
]
395+
);
385396
}
386397
}
387398

test/baselines/comments_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ type IdReference = {
8686
* - Use values from 0123456789 (Unicode 'DIGIT ZERO' (U+0030) to 'DIGIT NINE' (U+0039)) rather than superficially similiar Unicode symbols.
8787
* - Use '.' (Unicode 'FULL STOP' (U+002E)) rather than ',' to indicate a decimal point. Avoid using these symbols as a readability separator.
8888
*/
89-
export type Number = number;
89+
export type Number = number | \`\${number}\`;
9090
9191
/** Data type: Text. */
9292
export type Text = string;

test/baselines/data_type_union_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ type IdReference = {
5757
\\"@id\\": string;
5858
};
5959
60-
export type Number = number;
60+
export type Number = number | \`\${number}\`;
6161
6262
export type Text = string;
6363

test/baselines/deprecated_objects_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ type IdReference = {
8080
\\"@id\\": string;
8181
};
8282
83-
export type Number = number;
83+
export type Number = number | \`\${number}\`;
8484
8585
export type Text = string;
8686

test/baselines/inheritance_multiple_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ type IdReference = {
6161
\\"@id\\": string;
6262
};
6363
64-
export type Number = number;
64+
export type Number = number | \`\${number}\`;
6565
6666
export type Text = string;
6767

test/baselines/inheritance_one_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ type IdReference = {
5656
\\"@id\\": string;
5757
};
5858
59-
export type Number = number;
59+
export type Number = number | \`\${number}\`;
6060
6161
export type Text = string;
6262

0 commit comments

Comments
 (0)