Skip to content

TypeScript types #274

@sir4ur0n

Description

@sir4ur0n

So this is more an open discussion issue than an actual issue/feature request for now 😅 I want to get the ball rolling, and see where you stand on this.

I have migrated my code base to TypeScript in the last few days, and it makes for a smoother dev experience in my opinion, in particular when libraries provide types.

What do you think about providing LocusZoom TypeScript types? Apparently many libraries publish a @types/xxx NPM library, e.g. @types/locuszoom.

Here is a couple of concrete examples where it would be valuable, based on my (very limited, I admit) use of LZ so far:

  • a widget (say, set_state) has mandatory and optional arguments, but one needs to refer to the documentation and hope one does not make mistakes (or find out at runtime). Instead, if LZ provides the type, then the developer would instantly know they need to provide options with the right type, but all other fields would be optional. Something like
interface SetStateWidget {
  options: Array<SetStateOptionsConfigField>,
  button_html?: string,
  button_title?: string,
  show_selected?: bool,
  state_field?: string,
  custom_event_name?: string,
}

interface SetStateOptionsConfigField {
  display_name: string,
  value: any // or we could even make this interface generic on the type of `value`
}
  • one wants to subclass AssociationLZ but contact a different API which responds in a different format. One thus needs to override _normalizeResponse to adapt back the response to the format of UMich. With a return type in TypeScript, this would make things much simpler!
// In LocusZoom library
interface UMichAssocRow {
  analysis: string,
  ref_allele_freq?: number,
  // etc., maybe also add an index type to accept "any extra field"
}

class AssociationLZ {
  // ...
  _normalizeResponse(/* ... */): Array<UMichAssocRow> {
    // ...
  }
}

// In developer code
class CustomAssociationLZ extends AssociationLZ {
  _getUrl(/* ... */): string {
    return "https://my.custom/api";
  }

  _normalizeResponse(/* ... */): Array<UMichAssocRow> {
    // Here it's much simpler to implement, because TypeScript typechecker gives me errors and hints about the structure I need to return
  }
}

I reckon a major drawback is that since there is a significant API surface for LZ, it would take some work to provide the types for all its API. This is the major "problem" in my opinion.

Another con one could argue is that parts of LZ are intrinsically dynamic (e.g. the layout subscription mechanism: it's not really possible to know at compilation time the type of LocusZoom.Layouts.get("foo", "bar")). I don't think this is a real issue: TypeScript typechecker has mechanisms to elegantly step back in those situations, e.g. with any, type casting or index types. 99% of the code would benefit from types, and maybe 1% would not, but would not be blocked either. I think it's ok.

Maybe this could be mitigated by slowly migrating LocusZoom codebase itself to TypeScript? Once LZ is migrated to TS, then it should be a easy - I think - to have/generate its API types and publish to NPM.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions