@@ -6,13 +6,15 @@ import * as Instance from "@hyperjump/json-schema/instance/experimental";
66 * @import { ErrorHandler, ErrorObject } from "../index.d.ts"
77 */
88
9+ const ALL_TYPES = [ "null" , "boolean" , "number" , "string" , "array" , "object" , "integer" ] ;
10+
911/** @type ErrorHandler */
1012const type = async ( normalizedErrors , instance , localization ) => {
1113 /** @type ErrorObject[] */
1214 const errors = [ ] ;
1315
1416 if ( normalizedErrors [ "https://json-schema.org/keyword/type" ] ) {
15- let allowedTypes = new Set ( [ "null" , "boolean" , "number" , "string" , "array" , "object" , "integer" ] ) ;
17+ let allowedTypes = new Set ( ALL_TYPES ) ;
1618 const failedTypeLocations = [ ] ;
1719
1820 for ( const schemaLocation in normalizedErrors [ "https://json-schema.org/keyword/type" ] ) {
@@ -27,30 +29,50 @@ const type = async (normalizedErrors, instance, localization) => {
2729 const types = Array . isArray ( value ) ? value : [ value ] ;
2830 /** @type {Set<string> } */
2931 const keywordTypes = new Set ( types ) ;
30- allowedTypes = allowedTypes . intersection ( keywordTypes ) ;
32+ allowedTypes = intersectTypeSets ( allowedTypes , keywordTypes ) ;
3133 }
3234
3335 if ( allowedTypes . size === 0 ) {
3436 if ( failedTypeLocations . length > 0 ) {
3537 errors . push ( {
3638 message : localization . getConflictingTypeMessage ( ) ,
3739 instanceLocation : Instance . uri ( instance ) ,
38- schemaLocation : failedTypeLocations [ 0 ]
40+ schemaLocation : failedTypeLocations
3941 } ) ;
4042 }
41- } else {
42- for ( const schemaLocation of failedTypeLocations ) {
43- const keyword = await getSchema ( schemaLocation ) ;
44- errors . push ( {
45- message : localization . getTypeErrorMessage ( Schema . value ( keyword ) , Instance . typeOf ( instance ) ) ,
46- instanceLocation : Instance . uri ( instance ) ,
47- schemaLocation : schemaLocation
48- } ) ;
43+ } else if ( failedTypeLocations . length > 0 ) {
44+ if ( allowedTypes . has ( "number" ) ) {
45+ allowedTypes . delete ( "integer" ) ;
4946 }
47+ errors . push ( {
48+ message : localization . getTypeErrorMessage ( [ ...allowedTypes ] , Instance . typeOf ( instance ) ) ,
49+ instanceLocation : Instance . uri ( instance ) ,
50+ schemaLocation : failedTypeLocations . length === 1 ? failedTypeLocations [ 0 ] : failedTypeLocations
51+ } ) ;
5052 }
5153 }
5254
5355 return errors ;
5456} ;
5557
58+ /**
59+ * @param {Set<string> } a
60+ * @param {Set<string> } b
61+ * @returns {Set<string> }
62+ */
63+ const intersectTypeSets = ( a , b ) => {
64+ /** @type {Set<string> } */
65+ const intersection = new Set ( ) ;
66+ for ( const type of a ) {
67+ if ( b . has ( type ) ) {
68+ intersection . add ( type ) ;
69+ } else if ( type === "integer" && b . has ( "number" ) ) {
70+ intersection . add ( "integer" ) ;
71+ } else if ( type === "number" && b . has ( "integer" ) ) {
72+ intersection . add ( "integer" ) ;
73+ }
74+ }
75+ return intersection ;
76+ } ;
77+
5678export default type ;
0 commit comments