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

Revision 0.34.7 #1093

Merged
merged 4 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelog/0.34.0.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
### 0.34.0
- [Revision 0.34.7](https://github.com/sinclairzx81/typebox/pull/1093)
- Revert Ref(Schema) Signature with Deprecation Notice
- [Revision 0.34.6](https://github.com/sinclairzx81/typebox/pull/1090)
- Add Computed To Type and Kind Guards (IsSchema)
- [Revision 0.34.5](https://github.com/sinclairzx81/typebox/pull/1088)
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sinclair/typebox",
"version": "0.34.6",
"version": "0.34.7",
"description": "Json Schema Type Builder with Static Type Resolution for TypeScript",
"keywords": [
"typescript",
Expand Down
10 changes: 1 addition & 9 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -534,15 +534,7 @@ The following table lists the supported Json types. These types are fully compat
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const R = { │
│ x: Type.Number(), │ x: number, │ $ref: 'T' │
│ y: Type.Number() │ y: number │ } │
│ }, { $id: 'T' }) | } │ │
│ │ │ │
│ const R = Type.Ref(T) │ type R = T │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ const R = Type.Ref('T') │ type R = unknown │ const R = { $ref: 'T' } │
│ │ │ │
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
```
Expand Down
28 changes: 27 additions & 1 deletion src/type/ref/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import type { TSchema, SchemaOptions } from '../schema/index'
import { TypeBoxError } from '../error/index'
import { CreateType } from '../create/type'
import { Kind } from '../symbols/index'
import { TUnsafe } from '../unsafe/index'
import { Static } from '../static/index'

// ------------------------------------------------------------------
// TRef
Expand All @@ -38,7 +41,30 @@ export interface TRef<Ref extends string = string> extends TSchema {
static: unknown
$ref: Ref
}

export type TRefUnsafe<Type extends TSchema> = TUnsafe<Static<Type>>

/** `[Json]` Creates a Ref type.*/
export function Ref<Ref extends string>($ref: Ref, options?: SchemaOptions): TRef<Ref>
/**
* @deprecated `[Json]` Creates a Ref type. The referenced type MUST contain a $id. The Ref(TSchema) signature was
* deprecated on 0.34.0 in support of a new type referencing model (Module). Existing implementations using Ref(TSchema)
* can migrate using the following. The Ref(TSchema) validation behavior of Ref will be preserved how the construction
* of legacy Ref(TSchema) will require wrapping in TUnsafe (where TUnsafe is used for inference only)
*
* ```typescript
* const R = Type.Ref(T)
* ```
* to
*
* ```typescript
* const R = Type.Unsafe<Static<T>>(T.$id)
* ```
*/
export function Ref<Type extends TSchema>(type: Type, options?: SchemaOptions): TRefUnsafe<Type>
/** `[Json]` Creates a Ref type. The referenced type must contain a $id */
export function Ref<Ref extends string>($ref: Ref, options?: SchemaOptions): TRef<Ref> {
export function Ref(...args: any[]): unknown {
const [$ref, options] = typeof args[0] === 'string' ? [args[0], args[1]] : [args[0].$id, args[1]]
if (typeof $ref !== 'string') throw new TypeBoxError('Ref: $ref must be a string')
return CreateType({ [Kind]: 'Ref', $ref }, options) as never
}
27 changes: 23 additions & 4 deletions src/type/type/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import { Readonly, type TReadonlyWithFlag, type TReadonlyFromMappedResult } from
import { ReadonlyOptional, type TReadonlyOptional } from '../readonly-optional/index'
import { Record, type TRecordOrObject } from '../record/index'
import { Recursive, type TRecursive, type TThis } from '../recursive/index'
import { Ref, type TRef } from '../ref/index'
import { Ref, type TRef, type TRefUnsafe } from '../ref/index'
import { Required, type TRequired, type TRequiredFromMappedResult } from '../required/index'
import { Rest, type TRest } from '../rest/index'
import { type TSchema, type SchemaOptions } from '../schema/index'
Expand Down Expand Up @@ -259,9 +259,28 @@ export class JsonTypeBuilder {
public Recursive<T extends TSchema>(callback: (thisType: TThis) => T, options?: SchemaOptions): TRecursive<T> {
return Recursive(callback, options)
}
/** `[Json]` Creates a Ref type. */
public Ref<Ref extends string>($ref: Ref, options?: SchemaOptions): TRef<Ref> {
return Ref($ref, options)

/** `[Json]` Creates a Ref type.*/
public Ref<Ref extends string>($ref: Ref, options?: SchemaOptions): TRef<Ref>
/**
* @deprecated `[Json]` Creates a Ref type. The referenced type MUST contain a $id. The Ref(TSchema) signature was
* deprecated on 0.34.0 in support of a new type referencing model (Module). Existing implementations using Ref(TSchema)
* can migrate using the following. The Ref(TSchema) validation behavior of Ref will be preserved how the construction
* of legacy Ref(TSchema) will require wrapping in TUnsafe (where TUnsafe is used for inference only)
*
* ```typescript
* const R = Type.Ref(T)
* ```
* to
*
* ```typescript
* const R = Type.Unsafe<Static<T>>(T.$id)
* ```
*/
public Ref<Type extends TSchema>(type: Type, options?: SchemaOptions): TRefUnsafe<Type>
/** `[Json]` Creates a Ref type. The referenced type must contain a $id */
public Ref(...args: any[]): unknown {
return Ref(args[0] as string, args[1])
}
/** `[Json]` Constructs a type where all properties are required */
public Required<MappedResult extends TMappedResult>(type: MappedResult, options?: SchemaOptions): TRequiredFromMappedResult<MappedResult>
Expand Down
12 changes: 12 additions & 0 deletions test/runtime/compiler-ajv/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ import { Type } from '@sinclair/typebox'
import { Ok, Fail } from './validate'

describe('compiler-ajv/Ref', () => {
// ----------------------------------------------------------------
// Deprecated
// ----------------------------------------------------------------
it('Should validate for Ref(Schema)', () => {
const T = Type.Number({ $id: 'T' })
const R = Type.Ref(T)
Ok(R, 1234, [T])
Fail(R, 'hello', [T])
})
// ----------------------------------------------------------------
// Standard
// ----------------------------------------------------------------
it('Should should validate when referencing a type', () => {
const T = Type.Object(
{
Expand Down
12 changes: 12 additions & 0 deletions test/runtime/compiler/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ import { Ok, Fail } from './validate'
import { Assert } from '../assert/index'

describe('compiler/Ref', () => {
// ----------------------------------------------------------------
// Deprecated
// ----------------------------------------------------------------
it('Should validate for Ref(Schema)', () => {
const T = Type.Number({ $id: 'T' })
const R = Type.Ref(T)
Ok(R, 1234, [T])
Fail(R, 'hello', [T])
})
// ----------------------------------------------------------------
// Standard
// ----------------------------------------------------------------
it('Should should validate when referencing a type', () => {
const T = Type.Object(
{
Expand Down
21 changes: 21 additions & 0 deletions test/runtime/type/guard/kind/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@ import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'

describe('guard/kind/TRef', () => {
// ----------------------------------------------------------------
// Deprecated
// ----------------------------------------------------------------
it('Should guard for Ref(Schema) 1', () => {
const T = Type.Number({ $id: 'T' })
const R = Type.Ref(T)
Assert.IsTrue(KindGuard.IsRef(R))
Assert.IsTrue(typeof R['$ref'] === 'string')
})
it('Should guard for Ref(Schema) 2', () => {
const T = Type.Number()
Assert.Throws(() => Type.Ref(T))
})
it('Should guard for Ref(Schema) 3', () => {
// @ts-ignore
const T = Type.Number({ $id: null })
Assert.Throws(() => Type.Ref(T))
})
// ----------------------------------------------------------------
// Standard
// ----------------------------------------------------------------
it('Should guard for TRef', () => {
const T = Type.Number({ $id: 'T' })
const R = KindGuard.IsRef(Type.Ref(T))
Expand Down
21 changes: 21 additions & 0 deletions test/runtime/type/guard/type/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@ import { Type, CloneType } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'

describe('guard/type/TRef', () => {
// ----------------------------------------------------------------
// Deprecated
// ----------------------------------------------------------------
it('Should guard for Ref(Schema) 1', () => {
const T = Type.Number({ $id: 'T' })
const R = Type.Ref(T)
Assert.IsTrue(TypeGuard.IsRef(R))
Assert.IsTrue(typeof R['$ref'] === 'string')
})
it('Should guard for Ref(Schema) 2', () => {
const T = Type.Number()
Assert.Throws(() => Type.Ref(T))
})
it('Should guard for Ref(Schema) 3', () => {
// @ts-ignore
const T = Type.Number({ $id: null })
Assert.Throws(() => Type.Ref(T))
})
// ----------------------------------------------------------------
// Standard
// ----------------------------------------------------------------
it('Should guard for TRef', () => {
const T = Type.Number({ $id: 'T' })
const R = TypeGuard.IsRef(Type.Ref('T'))
Expand Down
12 changes: 12 additions & 0 deletions test/runtime/value/check/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ import { Type } from '@sinclair/typebox'
import { Assert } from '../../assert/index'

describe('value/check/Ref', () => {
// ----------------------------------------------------------------
// Deprecated
// ----------------------------------------------------------------
it('Should validate for Ref(Schema)', () => {
const T = Type.Number({ $id: 'T' })
const R = Type.Ref(T)
Assert.IsTrue(Value.Check(T, [T], 1234))
Assert.IsFalse(Value.Check(T, [T], 'hello'))
})
// ----------------------------------------------------------------
// Standard
// ----------------------------------------------------------------
it('Should should validate when referencing a type', () => {
const T = Type.Object(
{
Expand Down
Loading