Record and Union Conversion Logic (#361)

This commit is contained in:
sinclairzx81
2023-03-28 23:50:49 +09:00
committed by GitHub
parent e9f63d897b
commit e8b213c390
4 changed files with 38 additions and 5 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@sinclair/typebox",
"version": "0.26.5",
"version": "0.26.6",
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
"keywords": [
"typescript",
+14 -2
View File
@@ -28,6 +28,7 @@ THE SOFTWARE.
import * as Types from '../typebox'
import { ValueClone } from './clone'
import { ValueCheck } from './check'
// ----------------------------------------------------------------------------------------------
// Errors
@@ -129,7 +130,6 @@ export namespace ValueConvert {
function TryConvertBigInt(value: unknown) {
return IsStringNumeric(value) ? globalThis.BigInt(parseInt(value)) : IsNumber(value) ? globalThis.BigInt(value | 0) : IsValueFalse(value) ? 0 : IsValueTrue(value) ? 1 : value
}
function TryConvertString(value: unknown) {
return IsValueToString(value) ? value.toString() : IsSymbol(value) && value.description !== undefined ? value.description.toString() : value
}
@@ -229,7 +229,13 @@ export namespace ValueConvert {
return value
}
function Record(schema: Types.TRecord<any, any>, references: Types.TSchema[], value: any): unknown {
return value
const propertyKey = globalThis.Object.getOwnPropertyNames(schema.patternProperties)[0]
const property = schema.patternProperties[propertyKey]
const result = {} as Record<string, unknown>
for (const [propKey, propValue] of globalThis.Object.entries(value)) {
result[propKey] = Visit(property, references, propValue)
}
return result
}
function Ref(schema: Types.TRef<any>, references: Types.TSchema[], value: any): unknown {
const index = references.findIndex((foreign) => foreign.$id === schema.$ref)
@@ -261,6 +267,12 @@ export namespace ValueConvert {
return TryConvertUndefined(value)
}
function Union(schema: Types.TUnion, references: Types.TSchema[], value: any): unknown {
for (const subschema of schema.anyOf) {
const converted = Visit(subschema, references, value)
if (ValueCheck.Check(subschema, references, converted)) {
return converted
}
}
return value
}
function Uint8Array(schema: Types.TUint8Array, references: Types.TSchema[], value: any): unknown {
+5 -1
View File
@@ -3,5 +3,9 @@ import { Type } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('value/convert/Record', () => {
it('Should convert', () => {})
it('Should convert record value to numeric', () => {
const T = Type.Record(Type.String(), Type.Number())
const V = Value.Convert(T, { x: '42', y: '24', z: 'hello' })
Assert.deepEqual(V, { x: 42, y: '24', z: 'hello' })
})
})
+18 -1
View File
@@ -3,5 +3,22 @@ import { Type } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('value/convert/Union', () => {
it('Should convert', () => {})
it('Should convert union variant', () => {
const T = Type.Object({
x: Type.Union([Type.Number(), Type.Null()]),
})
const V1 = Value.Convert(T, { x: '42' })
const V2 = Value.Convert(T, { x: 'null' })
const V3 = Value.Convert(T, { x: 'hello' })
Assert.deepEqual(V1, { x: 42 })
Assert.deepEqual(V2, { x: null })
Assert.deepEqual(V3, { x: 'hello' })
})
it('Should convert first variant in ambiguous conversion', () => {
const T = Type.Object({
x: Type.Union([Type.Boolean(), Type.Number()]),
})
const V1 = Value.Convert(T, { x: '1' })
Assert.deepEqual(V1, { x: true })
})
})