Skip to content

Nominal typing and TypeScript > 2.7 #21625

Closed
@alexandru

Description

@alexandru

Hello,

TypeScript is structurally typed, but sometimes we need nominal typing, for interfaces / types, not classes.

For example one instance where nominal typing is needed is in encoding higher kinded types, which are needed in functional programming libraries, like fp-ts and funfix. The encoding currently used goes like this:

interface HK<F, A> {
  readonly _URI: F
  readonly _A: A
}

These are known as "phantom types", aka types that don't have a runtime footprint, their sole purpose being to aid the compiler in doing static type checks.

Unfortunately TypeScript 2.7 is breaking this encoding due to its new restriction to have all readonly properties initialized in the constructor. So if we are to keep using such an encoding, then we'd have to do:

class Box<A> extends HK<"box", A> {
  readonly _URI: "box" = undefined as any
  readonly _A: A = undefined as any
}

But this is not acceptable, because it has runtime ramifications, both _URI and _A being registered as properties on Box.prototype and that's very uncool, for one because it implies extra memory usage, but also because this encoding is very TypeScript-specific, as for JavaScript engines / code this has no value and the optimal encoding for Flow is different.

The current proposal is to use literal properties (with special chars that would make them unsuitable for usage as normal properties), which apparently TypeScript 2.7 doesn't touch:

interface HK<F, A> {
  readonly '-URI': F
  readonly '-A': A
}

My worry however is that this will be a temporary workaround.

I really do appreciate the tightening of the type system and the new strict settings that keep getting added, however as library authors we need an encoding that doesn't break between versions with the strictest settings active.

So, can we get an assurance that the above encoding won't break, or that if it does, it will get replaced by a feature that fixes this need (encoding of phantom types) for good?

And thanks for all your hard work 👏, in spite of TypeScript 2.7 breaking my code, the improvements look good and I understand more is on the way for 2.8.

Cheers,

Metadata

Metadata

Assignees

No one assigned

    Labels

    DiscussionIssues which may not have code impact

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions