5

I have a generic interface available to me as such:

CurriedFunction3<T1, T2, T3, R>: R

I would like to create a const binding that fills in some of those type arguments. Something like this:

type CurriedSorter<T> = CurriedFunction3<(obj: T) => any, string, T[], T[]>;

When I try to assign a const binding this type, however, I get an error:

type CurriedSorter<T> = CurriedFunction3<(obj: T) => any, string, T[], T[]>;

const sortFactory: CurriedSorter = uncurryN(3, flip(compose(
  unapply(sortWith),
  uncurryN(2, ifElse(
    compose(equals('DESC'), toUpper),
    always(descend),
    always(ascend),
  )),
)));

Generic type CurriedSorter requires 1 type argument(s).

The const binding sortFactory should be a function with one generic type parameter, to be used as such:

sortFactory<MyType>(
  prop('name'),
  'DESC',
  [{ name: 'foo' }, { name: 'bar' }]
) // returns `[{ name: 'bar' }, { name: 'foo' }]`

How can I generically type variable bindings in TypeScript? Is there any way to do this with TypeScript?

knpwrs
  • 15,691
  • 12
  • 62
  • 103
  • What is the type for `sortFactory` ? did you try mentioning the `T` in `const sortFactory: CurriedSorter`? – Niladri May 04 '18 at 15:58
  • `sortFactory` should be `CurriedSorter`, i.e., accept one generic type to pass to `CurriedSorter`. I am unsure of how to mention `T` in `const sortFactory`, that's what this question is about. When I do `const sortFactory: CurriedSorter` I get an error "Cannot find name 'T'". – knpwrs May 04 '18 at 16:08

1 Answers1

3

You can't have a bare T in a variable declaration's type because the T could potentially leak out of the value through a property. However, you can have a generic call signature as part of the type of the variable. Here's a self-contained example since I don't know what you've defined uncurryN, unapply, etc as:

type CurriedFunction3<T1, T2, T3, R> = (a: T1, b: T2, c: T3) => R;

type CurriedSorter<T> = CurriedFunction3<(obj: T) => any, string, T[], T[]>;

type CurriedSorterValue = {
    <T>(a: (obj: T) => any, b: string, c: T[]): T[];
}

const sortFactory: CurriedSorterValue = function (a, b, c) {
    return c;
}
Ryan Cavanaugh
  • 209,514
  • 56
  • 272
  • 235
  • What do you mean by `generic call signature` here? Does it mean to declare a type which is actually a type of function with generic signature? like `type CurriedSorterValue` – Niladri May 04 '18 at 18:29
  • Right; `(a: (obj: T) => any, b: string, c: T[]): T[];` is a generic call signature (which may be contained in a non-generic type), whereas `CurriedSorter` is a generic type. – Ryan Cavanaugh May 04 '18 at 18:34