sinclairzx81 / typebox

Json Schema Type Builder with Static Type Resolution for TypeScript
Other
4.56k stars 148 forks source link

Type.String().Optional() is accepted on ts-hint / ts-lint, and even build successfully; but of course, "Optional()" does not exists #908

Closed kevinfaveri closed 3 weeks ago

kevinfaveri commented 3 weeks ago

Is there something wrong with Typebox Type typings? Or are they by design "any" for any deep field? I do get the correct autocomplete when I type "Type.String" it offers me completion for the known fields; but the funky thing is that it allows to type anything else without throwing on TS build type or showing on VSCode as type error, example, anything of this works: Type.String().Optional() Type.String().Why() Type.String().Man()

Is this by design? Is there any way to enforce those wildcards / any deep field are not acceptable at build time?

sinclairzx81 commented 3 weeks ago

@kevinfaveri Hi,


Is this by design?

Yeah, this is a consequence of the design. The reason this is possible is because TypeBox types extend the following open interface (which permits any additional extra properties). TypeBox gives hints for the known additional properties (as given by the SchemaOptions interface), but for anything else, it just trusts you.

export interface SchemaOptions {
  $schema?: string
  $id?: string
  title?: string
  description?: string
  default?: any
  examples?: any
  readOnly?: boolean
  writeOnly?: boolean
  [prop: string]: any // meaning T.Optional and by extension T.Optional() (call expression) is allowed.
}

Note: The reason TypeBox uses any vs unknown is largely historical. The additional properties of any are mostly used for property hooks in downstream tooling, so changing to unknown has a potential to cause a lot of breakage (so reluctant to change in the near term). The ability to .chain() function calls off the end of schemas is very unfortunate though (and may look to revise things here in future)


Is there any way to enforce those wildcards / any deep field are not acceptable at build time?

Unfortunately no. Because the SchemaOptions is fully open to extension, it's very difficult to constrain without additional wrapping of the types. The appropriate solution here would be to have SchemaOptions constrain to unknown. This would at least warn of attempted member expression / call expression on the types. But as this can't be done for other reasons, things are largely at a impasse (at least for now)


Will close off this issue for now, but hopefully the above provides some insights into why this is possible. TypeBox is getting some fairly significant internal updates done to it's inference infrastructure for the next release (scheduled sometime near the end of this year). I will mark this issue as an aspect for review ... but for now, things are working as per design.

All this best S

kevinfaveri commented 3 weeks ago

Thanks sir!