Skip to content

Specialize declared generic interfaces based on parameter shape #13852

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
danvk opened this issue Feb 2, 2017 · 4 comments · May be fixed by hixio-mh/TypeScript#5
Closed

Specialize declared generic interfaces based on parameter shape #13852

danvk opened this issue Feb 2, 2017 · 4 comments · May be fixed by hixio-mh/TypeScript#5
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@danvk
Copy link
Contributor

danvk commented Feb 2, 2017

For typing something like underscore's _.chain, it would be helpful if interfaces could be extended based on the shape of their type parameters.

For example:

// These methods are available for any T.
declare interface Chainable<T> {
  value(): T;
}

// These methods are only available for array types.
declare interface Chainable<T[]> {
  map<U>(mapFn: (t: T) => U): Chainable<U[]>;
}

Existing type definitions try to infer whether T is an array, object, array of objects, etc. But this is cumbersome and they'll never be able to do it as well as TypeScript itself.

The snippet above doesn't parse with TypeScript 2.1.5:

[ts] Operator '>' cannot be applied to types 'undefined[]' and '{ map<U>(mapFn: (t: any) => U): Chainable<U[]>; }'.
@danvk
Copy link
Contributor Author

danvk commented Feb 28, 2017

maybe related to #12424

@mhegazy
Copy link
Contributor

mhegazy commented Mar 1, 2017

either #12424 or have some sort of overload on generic type parameters

@mhegazy mhegazy added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Mar 1, 2017
@danvk
Copy link
Contributor Author

danvk commented Apr 1, 2017

I wrote a post that touched on this issue and got some great feedback from the /r/javascript reddit. As it turns out, there's a workaround that already works: specialize by overloading the this parameter.

declare interface Chainable<T> {
  value(): T;  // This methods is available for any T.

  // This method is only available for array types, where T matches V[].
  map<U, V>(this: Chainable<V[]>, mapFn: (v: V) => U): Chainable<U[]>;
}

@danvk
Copy link
Contributor Author

danvk commented May 7, 2019

Overloading on the type of this works great. The lodash declarations in DefinitelyTyped do this now. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants