untyped icon indicating copy to clipboard operation
untyped copied to clipboard

versioned schema

Open danielroe opened this issue 3 years ago • 3 comments

Users may have schema keys that are only relevant for certain versions of the schema. We can produce one set of type declarations that allows users to specify the schema (or simply use entire schema definition).

For example:

export default {
  /**
   * @version ^2
   * @version ^1.2
   */
  foo: 'qux',

  /** @version >1.3 */
  bar: 'qux',

  baz: 'qux',
}

The generated .d.ts would be:

export default interface ConfigSchema<Version extends string = any> {
  /**
   * @version ^2
   * @version ^1.2
   */
  foo: SemverMatch<Version, '^2' | '^1.2'> extends true ? string : never

  /** @version >1.3 */
  bar: SemverMatch<Version, '>1.3'> extends true ? string : never

  baz: string
}

Then when using the interface we could do:

const config: ConfigSchema = {
  foo: 'test',
  bar: 'test',
  baz: 'test'
}

const versionedConfig: ConfigSchema<'1.2'> = {
  foo: 'test',
  // ts would complain that 'test' cannot be assigned to 'never'
  bar: 'test',
  baz: 'test'
}

(It might even be possible to remove the bar key entirely from the 1.2 versioned types.

As part of this we would add another field to schema types: versions which would contain an array of semver ranges and could be used in the runtime validation piece of the puzzle.

danielroe avatar Nov 25 '21 21:11 danielroe

I like idea of versioning with semver but do you think we can implement whole semver checking logic with a type like SemverMatch? (I guess it would be finally a limited subset of it)

What if we allow passing a semver filter when generating types/docs from schema instead? (Second idea of entirely removing from generated type)

PS: We would also need to specify schema declaration of version (untyped is not just a ts generator but also runtime lib).

pi0 avatar Nov 25 '21 21:11 pi0

On updates: Semver allowes combining multiple ranges in one. Why do we need an array of versions vs version?

pi0 avatar Nov 26 '21 09:11 pi0

Agree about single version 👍 The only issue is that JSdoc spec allows for separate @version tags, but I guess we can combine them with || ourselves?

For runtime behaviour, could I suggest that we have an optional version we pass to runtime schema normalizer (normalizeSchema) which validates each versioned key before attempting to normalize it?

danielroe avatar Nov 26 '21 09:11 danielroe