Skip to content

Type's generic type constraint on member level #1290

Closed
@Igorbek

Description

@Igorbek

This is a suggestion for spec change.

Problem

Sometimes type's members could only be applicable with some restrictions of enclosing type parameter (generic type constraints).

For instance, this is use case of RxJS:

var xs: Observable<Observable<string>>;
xs.mergeAll();  // mergeAll is applicable here

var ys: Observable<string>;
ys.mergeAll();  // mergeAll is NOT applicable here

Original Rx.NET Merge method implemented as C# extension method on type IObservable<IObservable<T>>. In RxJS it's implemented as an instance method.

Current RxJS typescript definition just use unsafe trick:

export interface Observable<T> {
  ...
  mergeAll(): T;
  ...
}

But it can be still unsafely called for as instance of any Observable<T>.

Possible solutions

Extension methods

Something like C# extension methods. But don't think it's useful in such cases.

declare extensions {
  mergeAll<T>(this Observable<Observable<T>> source): Observable<T>;
}

BTW, extensions method could be other cool feature, which change call method (from instance-like to static-like).

Multiple interface definitions with different constraints

interface A<T> { x(): void; }
interface A<T extends B> { y(): void; }
var a: A<number>;
var b: A<B>;

a.x(); b.x(); // ok
b.y(); // ok
a.y(); // error

Member-level constraints with reference to enclosing type arguments

interface A<T> {
  x(): void;
  y<T extends B>(): void; // only applicable if T extends B
  z<T extends B>: number; // for any property
  // alternative syntax options:
  <T extends B>z: number;  // 1

  z: number where T extends B;  // 2
  y(): void where T extends B;
}

I'll suggest this option. Moreover the previous solution options is special case of this one (incompatible constraints are merged on member level).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions