Ambient mapping from JSON schema to typescript, without transpilation. Use JSON schemas as a first-class citizen in Typescript.
There are many tools that convert between Typescript and JSON schema. Howewever, all of them do that with a transpilation step. Ambison uses the deep inference options in typescript 3 to infer the types directly from the JSON schema.
This is not a runtime library - it contains only a single generic type, AsTyped. AsTyped can take any Json schema and AsTypeds it to a typescript type.
As-typed is ambient only. To use, simply use the JSON schema as a type passed to the AsTyped
generic type instead of as a value.
For example:
AsTyped<{type: 'string'}>
will resolve to the typescript type string
, and AsTyped<{type: 'object' properties: {foo: {type: 'string'}}}>
will resolve to {foo: string}
in typescript.
Every JSON schema type casts to a particular typescript type, as far as possible by language limitations. The following is a table of how JSON schema types translate to Typescript types with asTyped
AsTyped<{type: 'string'}>
===string
AsTyped<{type: 'number'}>
===number
AsTyped<{type: 'boolean'}>
===boolean
AsTyped<{type: 'null'}>
===null
AsTyped<{type: 'undefined'}>
===undefined
-
Patterns are not supported. There is no regex validation in typescript Typescript issue 6579
-
Value validation (min, max etc) is not supported Typescript is not meant for value checking (at least currently).
AsTyped<{type: 'object', properties: {foo: {type: 'number'}}>
==={foo?: number}
AsTyped<{type: 'object', properties: {foo: {type: 'number'}, bar: {type: 'string}, required: ['foo']}>
==={foo: number, bar?: string}
AsTyped<{type: 'array', items: [{type: 'number'}, {type: 'string'}], additionalItems: {type: 'boolean'}}>
=== [number, string, ...boolean[]]
AsTyped<{type: 'array', items: {type: 'array', items: {type: 'string'}}}>
===string[][]
AsTyped<{type: 'object', properties: {arr: {type: 'array', items: {type: 'object', additionalProperties: {type: 'string'}}}}}
==={arr: {[name: string]: string}[]}
AsTyped<{type: 'array', items: {type: 'string
}}>===
string[]`
AsTyped<{type: 'array', items: [{type: 'string'}, {type: 'number'}]}>
===[string, number]
Due to typescript's missing variadic features, the max number of items in a tuple needs to be hardcoded, currently to 10. Typescript issue 5453
AsTyped<{type: 'array', items: [{type: 'string'}, {type: 'number'}], additionalItems: {type: 'string'}}}>
===[string, number, ...string[]]
AsTyped<{definitions: {foo: {$id: 'foo', type: 'number'}}, $ref: 'foo'}>
===number
AsTyped<{definitions: {str1: {$id: 'str1', $ref: 'str2'}, str2: {$id: 'str2', type: 'string'}}, $ref: 'str1'}>
===string
Reference by URL ('#/definitions/foo', 'other.json/foo') are not supported. Typescript doesn't allow inference by partial strings Typescript Issue 12754
Not
works mainly on primitive types, e.g. AsTyped<{not: {type: 'string'}}>
will resolve to number | object | any[] | boolean
AsTyped<{oneOf: [{type: 'string'}, {type: 'number'}]}>
===string | number
Currently doesn't work as expected, and resolves the same as anyOf. See Typescript issue 20863
AsTyped<{allOf: [{type: 'object', properties: {a: {type: 'number'}}}, {type: 'object', properties: {b: {type: 'string'}}}]}>
==={a?: number, b?: string}
AsTyped<{allOf: [{type: 'object', properties: {a: {type: 'number'}}}, {type: 'object', properties: {b: {type: 'string'}}, required: ['b']}]}>
==={a?: number, b: string} | {a?: number} | {b: string}
If/Then/Else
acts exactly like {oneOf: [{allOf: [If, Then]}, Else]}
. It's strange to have this sugar in the schema which doesn't reduce the verbosity.
Currently doesn't work as expected, for the same reasons as oneOf. Resolves to (If & Then) | Else
, which is not an accurate translation.
See Typescript issue 20863