Skip to content

Commit

Permalink
Revision 0.31.16 (#605)
Browse files Browse the repository at this point in the history
* Support Infinite Template Literal Record Key

* Tests

* Version
  • Loading branch information
sinclairzx81 authored Sep 25, 2023
1 parent edd7578 commit dc4e70d
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 6 deletions.
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.31.15",
"version": "0.31.16",
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
"keywords": [
"typescript",
Expand Down
4 changes: 2 additions & 2 deletions src/typebox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -656,11 +656,11 @@ export type TRecordFromUnionRest<K extends TSchema[], T extends TSchema> = K ext
L extends TLiteralNumber ? TRecordFromUnionLiteralNumber<L, T> & TRecordFromUnionRest<AssertRest<R>, T> :
{}) : {}
export type TRecordFromUnion<K extends TSchema[], T extends TSchema> = Ensure<TObject<AssertProperties<Evaluate<TRecordFromUnionRest<K, T>>>>>
export type TRecordFromTemplateLiteralKeyInfinite<T extends TSchema> = Ensure<TRecord<TString, T>>
export type TRecordFromTemplateLiteralKeyInfinite<K extends TTemplateLiteral, T extends TSchema> = Ensure<TRecord<K, T>>
export type TRecordFromTemplateLiteralKeyFinite<K extends TTemplateLiteral, T extends TSchema, I = Static<K>> = Ensure<TObject<Evaluate<{ [_ in Assert<I, string>]: T }>>>
// prettier-ignore
export type TRecordFromTemplateLiteralKey<K extends TTemplateLiteral, T extends TSchema> = IsTemplateLiteralFinite<K> extends false
? TRecordFromTemplateLiteralKeyInfinite<T>
? TRecordFromTemplateLiteralKeyInfinite<K, T>
: TRecordFromTemplateLiteralKeyFinite<K, T>
export type TRecordFromLiteralStringKey<K extends TLiteralString, T extends TSchema> = Ensure<TObject<{ [_ in K['const']]: T }>>
export type TRecordFromLiteralNumberKey<K extends TLiteralNumber, T extends TSchema> = Ensure<TObject<{ [_ in K['const']]: T }>>
Expand Down
63 changes: 63 additions & 0 deletions test/runtime/compiler-ajv/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,67 @@ describe('compiler-ajv/Record', () => {
const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean() })
Ok(T, { 1: '', 2: '', x: true })
})
// ----------------------------------------------------------------
// TemplateLiteral
// ----------------------------------------------------------------
it('TemplateLiteral 1', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number(), { additionalProperties: false })
Ok(R, {
key0: 1,
key1: 1,
key2: 1,
})
})
it('TemplateLiteral 2', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
Ok(R, { keyA: 0 })
})
it('TemplateLiteral 3', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number(), { additionalProperties: false })
Fail(R, { keyA: 0 })
})
it('TemplateLiteral 4', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
const I = Type.Intersect([R, T], { unevaluatedProperties: false })
Ok(I, {
x: 1,
y: 2,
key0: 1,
key1: 1,
key2: 1,
})
})
it('TemplateLiteral 5', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
const I = Type.Intersect([R, T])
Ok(I, {
x: 1,
y: 2,
z: 3,
key0: 1,
key1: 1,
key2: 1,
})
})
it('TemplateLiteral 6', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
const I = Type.Intersect([R, T], { unevaluatedProperties: false })
Fail(I, {
x: 1,
y: 2,
z: 3,
key0: 1,
key1: 1,
key2: 1,
})
})
})
63 changes: 63 additions & 0 deletions test/runtime/compiler/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,67 @@ describe('compiler/Record', () => {
const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean() })
Ok(T, { 1: '', 2: '', x: true })
})
// ----------------------------------------------------------------
// TemplateLiteral
// ----------------------------------------------------------------
it('TemplateLiteral 1', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number(), { additionalProperties: false })
Ok(R, {
key0: 1,
key1: 1,
key2: 1,
})
})
it('TemplateLiteral 2', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
Ok(R, { keyA: 0 })
})
it('TemplateLiteral 3', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number(), { additionalProperties: false })
Fail(R, { keyA: 0 })
})
it('TemplateLiteral 4', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
const I = Type.Intersect([R, T], { unevaluatedProperties: false })
Ok(I, {
x: 1,
y: 2,
key0: 1,
key1: 1,
key2: 1,
})
})
it('TemplateLiteral 5', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
const I = Type.Intersect([R, T])
Ok(I, {
x: 1,
y: 2,
z: 3,
key0: 1,
key1: 1,
key2: 1,
})
})
it('TemplateLiteral 6', () => {
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
const I = Type.Intersect([R, T], { unevaluatedProperties: false })
Fail(I, {
x: 1,
y: 2,
z: 3,
key0: 1,
key1: 1,
key2: 1,
})
})
})
17 changes: 16 additions & 1 deletion test/static/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ import { Type, Static } from '@sinclair/typebox'

Expect(T).ToStatic<Record<number, string>>()
}

{
enum E {
A = 'X',
Expand All @@ -80,3 +79,19 @@ import { Type, Static } from '@sinclair/typebox'
const T = Type.Record(Type.Enum(E), Type.Number())
Expect(T).ToStatic<{}>()
}
{
// should support infinite record keys
// https://github.com/sinclairzx81/typebox/issues/604
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
Expect(R).ToStatic<Record<`key${number}`, number>>()
}
{
// should support infinite record keys with intersect
// https://github.com/sinclairzx81/typebox/issues/604
const K = Type.TemplateLiteral('key${number}')
const R = Type.Record(K, Type.Number())
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
const I = Type.Intersect([R, T])
Expect(I).ToStatic<Record<`key${number}`, number> & { x: number; y: number }>()
}

0 comments on commit dc4e70d

Please sign in to comment.