aws / jsii

jsii allows code in any language to naturally interact with JavaScript classes. It is the technology that enables the AWS Cloud Development Kit to deliver polyglot libraries from a single codebase!
https://aws.github.io/jsii
Apache License 2.0
2.63k stars 244 forks source link

Type definitions that only exist in TypeScript (don't get translated) #2886

Open rix0rrr opened 3 years ago

rix0rrr commented 3 years ago

:rocket: Feature Request

Affected Languages

Description

Here's a funky feature request:

Type definitions that stay in TypeScript, and don't get translated by jsii

In other languages, we would translate them like any.

Motivating example here is a CodeBuild buildspec: https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html

We'd like to type this structure so that we can model it and type-check it in TypeScript:

BuildSpec.fromObject({
  phasse: {  // <---- ERROR! TYPO!
    // ...
  }
})

FAQ

Why can't it just be a regular type definition?

Well, there are funky fields in there that probably don't play well with jsii and translation. Example:

image

JSII wouldn't like these field names. Yet, they are what they are and we cannot change them.

Why can't you just re-model everything and fix the names?

Well we could, but:

  1. We can't change it in-place:
    • It would be backwards breaking (so that's already right out the door); but also
    • Users would lose the ability to copy/paste an existing JSON blob into their code, and it's pretty important to be able to do that.
  2. We could add a new constructor, so we have BuildSpec.fromObject(object: any) and BuildSpec.fromBuildSpec(spec: BuildSpecProps).
    • However, now it will be confusing to casual users which one they would want, and they might accidentally copy/paste snippets meant for BuildSpec.fromBuildSpec() into BuildSpec.fromObject(), which will happily type check but not do what they want.

Proposed Solution

I feel a good additional feature to jsii (which would allow us to add reasonable type checking for TS users ), would be to have a feature like this:

/**
 * Type definition only exists in TypeScript
 *
 * @nojsii
 */
export interface BuildSpecProps {
  // ...
}

class BuildSpec {
  // The following gets translated as if it were written as 'public static fromObject(object: any)' 
  public static fromObject(object: BuildSpecProps) { 
  }
}
hoegertn commented 3 years ago

I would love this. I can also think of some use cases with generics or union types that could help in TS and be typed differently in other languages.

RomainMuller commented 3 years ago

Counter-proposition... How about allowing a TSDoc-annotation that allows the developer to force a particular declaration to be interpreted as a compatible semantic structure:

/**
 * This interface would normally be considered a behavioural interface
 * because it's name starts with a capital `I`, however, this is a struct in
 * this particular case... Just because `IP`...
 * 
 * @jsii struct
 */
export interface IPRange { /* ... */ }

/**
 * This interface is a specialised JSON value. Keys should not be
 * case-converted in any way, and in fact, this type should be represented
 * as a generic dict/map/JObject/... in other languages.
 * 
 * @jsii json
 */
export interface BuildSpec { /* ... */ }

This would however have implication on the quality of the documentation for those types... In the second case, since the fields would be "erased" from the jsii Assembly, all their documentation would effectively be... gone.

This also creates an asymmetry between how helpful the type checker is in TypeScript and in other languages (although arguably this already exists around type unions).

rix0rrr commented 3 years ago

I agree this potentially being a two-birds-one-stone kind of change. If you feel the code paths and/or concepts are similar enough to combine... sure! All for it.