Giter Site home page Giter Site logo

types's Introduction

Ramda

A practical functional library for JavaScript programmers.

Build Status npm module deno land nest badge Gitter

Why Ramda?

There are already several excellent libraries with a functional flavor. Typically, they are meant to be general-purpose toolkits, suitable for working in multiple paradigms. Ramda has a more focused goal. We wanted a library designed specifically for a functional programming style, one that makes it easy to create functional pipelines, one that never mutates user data.

What's Different?

The primary distinguishing features of Ramda are:

  • Ramda emphasizes a purer functional style. Immutability and side-effect free functions are at the heart of its design philosophy. This can help you get the job done with simple, elegant code.

  • Ramda functions are automatically curried. This allows you to easily build up new functions from old ones simply by not supplying the final parameters.

  • The parameters to Ramda functions are arranged to make it convenient for currying. The data to be operated on is generally supplied last.

The last two points together make it very easy to build functions as sequences of simpler functions, each of which transforms the data and passes it along to the next. Ramda is designed to support this style of coding.

Introductions

Philosophy

Using Ramda should feel much like just using JavaScript. It is practical, functional JavaScript. We're not introducing lambda expressions in strings, we're not borrowing consed lists, we're not porting over all of the Clojure functions.

Our basic data structures are plain JavaScript objects, and our usual collections are JavaScript arrays. We also keep other native features of JavaScript, such as functions as objects with properties.

Functional programming is in good part about immutable objects and side-effect free functions. While Ramda does not enforce this, it enables such style to be as frictionless as possible.

We aim for an implementation both clean and elegant, but the API is king. We sacrifice a great deal of implementation elegance for even a slightly cleaner API.

Last but not least, Ramda strives for performance. A reliable and quick implementation wins over any notions of functional purity.

Installation

To use with node:

$ npm install ramda

Then in the console:

const R = require('ramda');

To use directly in Deno:

import * as R from "https://deno.land/x/[email protected]/mod.ts";

or using Nest.land:

import * as R from "https://x.nest.land/[email protected]/mod.ts";

To use directly in the browser:

<script src="path/to/yourCopyOf/ramda.js"></script>

or the minified version:

<script src="path/to/yourCopyOf/ramda.min.js"></script>

or from a CDN, either cdnjs:

<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.30.0/ramda.min.js"></script>

or one of the below links from jsDelivr:

<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/ramda.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/ramda@latest/dist/ramda.min.js"></script>

(note that using latest is taking a significant risk that ramda API changes could break your code.)

These script tags add the variable R on the browser's global scope.

Or you can inject ramda into virtually any unsuspecting website using the bookmarklet.

Note for versions > 0.25 Ramda versions > 0.25 don't have a default export. So instead of import R from 'ramda';, one has to use import * as R from 'ramda'; Or better yet, import only the required functions via import { functionName } from 'ramda';

Note for ES6 module and browsers In order to access to the ES6 module in browsers, one has to provide the content of the es directory (see below for the build instructions) and use import * as R from './node_modules/ramda/es/index.js';

Build

npm run build creates es, src directories and updates both dist/ramda.js and dist/ramda.min.js

Partial Builds

It is possible to build Ramda with a subset of the functionality to reduce its file size. Ramda's build system supports this with command line flags. For example if you're using R.compose, R.reduce, and R.filter you can create a partial build with:

npm run --silent partial-build compose reduce filter > dist/ramda.custom.js

This requires having Node/io.js installed and ramda's dependencies installed (just use npm install before running partial build).

Documentation

Please review the API documentation.

Also available is our Cookbook of functions built from Ramda that you may find useful.

The Name

Ok, so we like sheep. That's all. It's a short name, not already taken. It could as easily have been eweda, but then we would be forced to say eweda lamb!, and no one wants that. For non-English speakers, lambs are baby sheep, ewes are female sheep, and rams are male sheep. So perhaps ramda is a grown-up lambda... but probably not.

Running The Test Suite

Console:

To run the test suite from the console, you need to have mocha installed:

npm install -g mocha

Then from the root of the project, you can just call

mocha

Alternately, if you've installed the dependencies, via:

npm install

then you can run the tests (and get detailed output) by running:

npm test

Browser:

You can use testem to test across different browsers (or even headlessly), with livereloading of tests. Install testem (npm install -g testem) and run testem. Open the link provided in your browser and you will see the results in your terminal.

If you have PhantomJS installed, you can run testem -l phantomjs to run the tests completely headlessly.

Usage

For v0.25 and up, import the whole library or pick ES modules directly from the library:

import * as R from 'ramda'

const {identity} = R
R.map(identity, [1, 2, 3])

Destructuring imports from ramda does not necessarily prevent importing the entire library. You can manually cherry-pick methods like the following, which would only grab the parts necessary for identity to work:

import identity from 'ramda/src/identity'

identity()

Manually cherry picking methods is cumbersome, however. Most bundlers like Webpack and Rollup offer tree-shaking as a way to drop unused Ramda code and reduce bundle size, but their performance varies, discussed here. Here is a summary of the optimal setup based on what technology you are using:

  1. Webpack + Babel - use babel-plugin-ramda to automatically cherry pick methods. Discussion here, example here
  2. Webpack only - use UglifyJS plugin for treeshaking along with the ModuleConcatenationPlugin. Discussion here, with an example setup here
  3. Rollup - does a fine job properly treeshaking, no special work needed; example here

Typings

Translations

Funding

If you wish to donate to Ramda please see our Open Collective page. Thank you!

Acknowledgements

Thanks to J. C. Phillipps for the Ramda logo. Ramda logo artwork © 2014 J. C. Phillipps. Licensed Creative Commons CC BY-NC-SA 3.0.

types's People

Contributors

gerkindev avatar harris-miller avatar hd-o avatar jeysal avatar lax4mike avatar moyuscript avatar nemo108 avatar ranneyd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

types's Issues

keys() to pick() typing problem

tldr: passing result of keys() into pick() reports an error, it can be solved by doing some quite dirty casting, better fix could be by updating the typing in pick (see Fix block bellow), but I´m not sure of the intentions of current implementation - thus this issue to discuss it.

/*
 * The usecase is I have an object that gets partially modified on FE
 * changes can be "flat" (on simple props like value), or also "nested" (eg on obj.body)
 */
interface Alpha {
  _id: string;
  name: string;
  value: string;
  description: string;
  obj: {
    head: string;
    body: string;
  }
}

interface AlphaPatch extends PartialDeep<Alpha> {
  // to make ID required, we need it for db filter
  _id: string;
}

function AlphaTest() {
  // in real app patch comes from the FE in Request body
  const alphaPatch: AlphaPatch = {
    _id: 'id',
    name: 'patched name',
    obj: {
      body: 'patched body',
    }
  };

  // in real app complete object is loaded from db, _id from patch is used for identification to load it
  const alpha: Alpha = {
    _id: 'id',
    name: 'name',
    value: 'value',
    description: 'description',
    obj: {
      head: 'obj.head',
      body: 'obj.body',
    },
  };

  /*
   * now because I dont want to just deep merge whole alpha with patch but I still need deep values in my patch
   * I'm trying to pick the keys, but pick reports an error:
   * Argument of type '("name" | "value" | "description" | "obj")[]' is not assignable to parameter of type 'readonly [keyof Alpha, ...(keyof Alpha)[]]'.
   * Source provides no match for required element at position 0 in target.ts(2345)
   */
  const { _id, ...patch } = alphaPatch;
  const keysToUpdate = keys(patch);
  const currentAlpha = pick(keysToUpdate, alpha);
  const patchWithAlphaDeep = mergeDeepRight(currentAlpha, patch);
}

Fix:

// this is current typings for pick
export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;

// this will fix it, look at Names;
declare module 'ramda' {
  export function pick<U, const Names extends readonly (keyof U)[]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
}

I'm not sure whether this typing on pick is intentional or not / what kind of purpose this typings serves, but anyway it doesn´t seems right that it´s impossible to pass result of keys() into pick(). I did some experiments with trying to recasting it, I made it "work" but the type wasn't reflecting reality keys(patch) as [keyof PartialDeep<Alpha>]; - that´s not right, there can be more than just 1 item in the array. Following cast will be correct, but it just feels dirty keys(patch) as [keyof PartialDeep<Alpha>, ...(keyof PartialDeep<Alpha>)[]];.

So my question is - is there a reasoning for having the typing for pick this way?

I found this change three weeks ago: https://github.com/ramda/types/pull/52/files @Harris-Miller

propEq type doesn't account for optional properties

type DemoType = {
	optionalProp?: string
}

const filteredList = propEq('Yes', 'optionalProp')({ optionalProp: 'Yes' } as DemoType)

This produces this error:

Argument of type 'DemoType' is not assignable to parameter of type 'Record<"optionalProp", string>'. Types of property 'optionalProp' are incompatible. Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.

I feel like this should work just fine? The code runs as expected, just produces a the error.

it doesn't error if you pass all parameters at the same time rather than using the curried functions. I'm really not sure why.
propEq('Yes', 'optionalProp', { optionalProp: 'Yes' } as DemoType)

I've forked the project and written a failing test, but sadly I'm not proficient enough at typescript to write something that does any type guarding but allows my use case.

@types/ramda parity

Make sure all function type definition either meets or beats what is in @types/ramda

  • add
  • addIndex
  • adjust
  • all
  • allPass
  • always
  • and
  • andThen
  • any
  • anyPass
  • ap
  • aperture
  • append
  • apply
  • applySpec
  • applyTo
  • ascend
  • assoc
  • assocPath
  • binary
  • bind
  • both
  • call
  • chain
  • clamp
  • clone
  • collectBy
  • comparator
  • complement
  • compose
  • composeWith
  • concat
  • cond
  • construct
  • constructN
  • converge
  • count
  • countBy
  • curry
  • curryN
  • dec
  • defaultTo
  • descend
  • difference
  • differenceWith
  • dissoc
  • dissocPath
  • divide
  • drop
  • dropLast
  • dropLastWhile
  • dropRepeats
  • dropRepeatsBy
  • dropRepeatsWith
  • dropWhile
  • either
  • empty
  • endsWith
  • eqBy
  • eqProps
  • equals
  • evolve
  • F
  • filter
  • find
  • findIndex
  • findLast
  • findLastIndex
  • flatten
  • flip
  • forEach
  • forEachObjIndexed
  • fromPairs
  • groupBy
  • groupWith
  • gt
  • gte
  • has
  • hasIn
  • hasPath
  • head
  • identical
  • identity
  • ifElse
  • inc
  • includes
  • indexBy
  • indexOf
  • init
  • innerJoin
  • insert
  • insertAll
  • intersection
  • intersperse
  • into
  • invert
  • invertObj
  • invoker
  • is
  • isEmpty
  • isNil
  • isNotNil
  • join
  • juxt
  • keys
  • keysIn
  • last
  • lastIndexOf
  • length
  • lens
  • lensIndex
  • lensPath
  • lensProp
  • lift
  • liftN
  • lt
  • lte
  • map
  • mapAccum
  • mapAccumRight
  • mapObjIndexed
  • match
  • mathMod
  • max
  • maxBy
  • mean
  • median
  • memoizeWith
  • mergeAll
  • mergeDeepLeft
  • mergeDeepRight
  • mergeDeepWith
  • mergeDeepWithKey
  • mergeLeft
  • mergeRight
  • mergeWith
  • mergeWithKey
  • min
  • minBy
  • modulo
  • move
  • multiply
  • nAry
  • negate
  • none
  • not
  • nth
  • nthArg
  • o
  • objOf
  • of
  • omit
  • on
  • once
  • or
  • otherwise
  • over
  • pair
  • partial
  • partialObject
  • partialRight
  • partition
  • path
  • pathEq
  • pathOr
  • pathSatisfies
  • paths
  • pick
  • pickAll
  • pickBy
  • pipe
  • pipeWith
  • pluck
  • prepend
  • product
  • project
  • promap
  • prop
  • propEq
  • propIs
  • propOr
  • propSatisfies
  • props
  • range
  • reduce
  • reduceBy
  • reduceRight
  • reduceWhile
  • reduced
  • reject
  • remove
  • repeat
  • replace
  • reverse
  • scan
  • set
  • slice
  • sort
  • sortBy
  • sortWith
  • split
  • splitAt
  • splitEvery
  • splitWhen
  • splitWhenever
  • startsWith
  • subtract
  • sum
  • symmetricDifference
  • symmetricDifferenceWith
  • T
  • tail
  • take
  • takeLast
  • takeLastWhile
  • takeWhile
  • tap
  • test
  • thunkify
  • times
  • toLower
  • toPairs
  • toPairsIn
  • toString
  • toUpper
  • transduce
  • transpose
  • traverse
  • trim
  • tryCatch
  • type
  • unapply
  • unary
  • uncurryN
  • unfold
  • union
  • unionWith
  • uniq
  • uniqBy
  • uniqWith
  • unless
  • unnest
  • until
  • update
  • useWith
  • values
  • valuesIn
  • view
  • when
  • where
  • whereEq
  • without
  • xor
  • xprod
  • zip
  • zipObj
  • zipWith

0.29.2 breaks tests on DT

From https://dev.azure.com/definitelytyped/DefinitelyTyped/_build/results?buildId=155148&view=logs&j=9d906afe-3eb5-5d79-316d-86f3f3fa360c&t=09716206-abc7-5ba2-2ea2-6c6fe97a3aad&l=12352:

Error in ramda
Error: /home/vsts/work/1/s/types/ramda/test/find-tests.ts:5:30
ERROR: 5:30   expect  [email protected] compile error: 
Argument of type '{ a: number; }[]' is not assignable to parameter of type 'readonly Record<2, any>[]'.
  Property '2' is missing in type '{ a: number; }' but required in type 'Record<2, any>'.
ERROR: 6:30   expect  [email protected] compile error: 
Argument of type '{ a: number; }[]' is not assignable to parameter of type 'readonly Record<4, any>[]'.
  Property '4' is missing in type '{ a: number; }' but required in type 'Record<4, any>'.

/home/vsts/work/1/s/types/ramda/test/findIndex-tests.ts:5:35
ERROR: 5:35   expect  [email protected] compile error: 
Argument of type '{ a: number; }[]' is not assignable to parameter of type 'readonly Record<2, any>[]'.
  Property '2' is missing in type '{ a: number; }' but required in type 'Record<2, any>'.
ERROR: 6:35   expect  [email protected] compile error: 
Argument of type '{ a: number; }[]' is not assignable to parameter of type 'readonly Record<4, any>[]'.
  Property '4' is missing in type '{ a: number; }' but required in type 'Record<4, any>'.

/home/vsts/work/1/s/types/ramda/test/findLast-tests.ts:8:34
ERROR: 8:34   expect  [email protected] compile error: 
Argument of type '{ a: number; b: number; }[]' is not assignable to parameter of type 'readonly Record<1, any>[]'.
  Property '1' is missing in type '{ a: number; b: number; }' but required in type 'Record<1, any>'.
ERROR: 9:34   expect  [email protected] compile error: 
Argument of type '{ a: number; b: number; }[]' is not assignable to parameter of type 'readonly Record<4, any>[]'.
  Property '4' is missing in type '{ a: number; b: number; }' but required in type 'Record<4, any>'.

/home/vsts/work/1/s/types/ramda/test/findLastIndex-tests.ts:8:39
ERROR: 8:39   expect  [email protected] compile error: 
Argument of type '{ a: number; b: number; }[]' is not assignable to parameter of type 'readonly Record<1, any>[]'.
  Property '1' is missing in type '{ a: number; b: number; }' but required in type 'Record<1, any>'.
ERROR: 9:39   expect  [email protected] compile error: 
Argument of type '{ a: number; b: number; }[]' is not assignable to parameter of type 'readonly Record<4, any>[]'.
  Property '4' is missing in type '{ a: number; b: number; }' but required in type 'Record<4, any>'.

/home/vsts/work/1/s/types/ramda/test/propEq-tests.ts:10:11
ERROR: 10:11  expect  [email protected] compile error: 
Type '(obj: Record<"bar", any>) => boolean' is not assignable to type '(obj: Record<"foo", "bar">) => boolean'.
  Types of parameters 'obj' and 'obj' are incompatible.
    Property 'bar' is missing in type 'Record<"foo", "bar">' but required in type 'Record<"bar", any>'.
ERROR: 12:11  expect  [email protected] compile error: 
Type '(obj: Record<5, any>) => boolean' is not assignable to type '(obj: Record<"baz", number>) => boolean'.
  Types of parameters 'obj' and 'obj' are incompatible.
    Property '5' is missing in type 'Record<"baz", number>' but required in type 'Record<5, any>'.
ERROR: 14:11  expect  [email protected] compile error: 
Type '(obj: Record<"qwerty", any>) => boolean' is not assignable to type '(obj: Record<number, string>) => boolean'.
  Types of parameters 'obj' and 'obj' are incompatible.
    Property 'qwerty' is missing in type 'Record<number, string>' but required in type 'Record<"qwerty", any>'.
ERROR: 29:22  expect  [email protected] compile error: 
Argument of type 'Obj' is not assignable to parameter of type 'Record<1, any>'.
  Property '1' is missing in type 'Obj' but required in type 'Record<1, any>'.
ERROR: 30:22  expect  [email protected] compile error: 
Argument of type 'Obj' is not assignable to parameter of type 'Record<4, any>'.
  Property '4' is missing in type 'Obj' but required in type 'Record<4, any>'.
ERROR: 43:28  expect  [email protected] compile error: 
Argument of type 'A' is not assignable to parameter of type 'Record<"", any>'.
  Property '""' is missing in type 'A' but required in type 'Record<"", any>'.

Conditional types

Hello!

I've been messing around with my example and I think I've narrowed the issue down to the fact that the following doesn't work:

expectType<string>(R.defaultTo('This file', undefined));

Here are the type definitions:

export function defaultTo<T, U>(a: T, b: U | null | undefined): T | U;
export function defaultTo<T>(a: T): <U>(b: U | null | undefined) => T | U;

I think the problem stems from the result type being T | U, which in this case would include undefined. I think we need to somehow use conditional types or something to make the types more aware about how the function behaves.

I assume this would be a problem for a bunch of other types too, like propOr, etc.

I don't know much about conditional types and I'm going to read those docs and do more research tomorrow, but I just wanted to post this to see if anyone else has any insight into this issue!

mergeDeepLeft behaves differently than in @types/ramda

The following example has stopped working, since @types/ramda uses ramda-types:

import { mergeDeepLeft } from "ramda";

const translations = [
  { lang: "de", contact: { email: "[email protected]", emailLabel: "E-Mail" } },
  { lang: "en", contact: { emailLabel: "Email" } }
];

function merge<T extends { lang: string }>(arr: T[]) {
  return mergeDeepLeft(arr[0], arr[1]) as T;
}

merge(translations);

Error message:

Conversion of type 'Assign<T, [T], "deep", BuiltIn, undefined>' to type 'T' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  'T' could be instantiated with an arbitrary type which could be unrelated to 'Assign<T, [T], "deep", BuiltIn, undefined>'.ts(2352)

Please ignore in case this was done intentionally.

[0.29.9] `pluck` inside `pipe` get ts error

The error msg:

Argument of type '{ <U extends O[keyof O], UK extends keyof U, O extends Record<string, any>>(obj: "value" extends UK ? O : never): { [OK in keyof O]: O[OK]["value"]; }; <U extends readonly unknown[] | Record<"value", any>>(list: readonly U[]): U extends readonly (infer T)[] ? T[] : U extends Record<...> ? T[] : never; }' is not assignable to parameter of type '(...args: Data[][]) => (number | null)[]'.
  Type '{ [x: string]: any; }' is missing the following properties from type '(number | null)[]': length, pop, push, concat, and 25 more.

image

Here is a minimal repo to reproduce the error
https://codesandbox.io/p/devbox/vm2hyt?file=%2Fsrc%2Findex.ts%3A7%2C22

I am not sure if my type in pipe<...> is wrong but it works in 0.29.4

`assoc` returns a narrower type than what is passed

Summary

assoc sometimes returns a more narrow type than what is passed to it. Since assoc never removes props, this feels wrong from a type perspective. I would expect assoc to only add or modify props, never remove.

In the example below, a complex type with 2 props is typed as Record<'flag', bool> after passing through assoc

Dependencies

Example

import { assoc } from "ramda";

type OriginalType = {
  name: string;
  flag: boolean;
};

function takesAnOriginalType(original: OriginalType) {
  console.log(original);
}

const array: OriginalType[] = [{ name: "test", flag: true }];

const mapped = array.map(assoc("flag", false));

takesAnOriginalType(mapped);
                    ^^^^^^

Error

const mapped: Record<"flag", boolean>[]
Argument of type 'Record<"flag", boolean>[]' is not assignable to parameter of type 'OriginalType'.
  Type 'Record<"flag", boolean>[]' is missing the following properties from type 'OriginalType': name, flagts(2345)

`filter` chooses wrong type overload when used with `map`.

This works:

const maybeStrings: (string | undefined)[] = ["a", undefined, "b"];
const strings: string[] = filter(isNotNil<string>)(maybeStrings);

But this doesn't, when involving a map (which is an extremely common use case)

const arrayOfMaybeStringArrays: (string | undefined)[][] = [["a", undefined, "b"]];
const arrayOfStringArrays: string[] = map(filter(isNotNil<string>))(arrayOfMaybeStringArrays);
error TS2322: Type 'Dictionary<string>[]' is not assignable to type 'string[][]'.
  Type 'Dictionary<string>' is missing the following properties from type 'string[]': length, pop, push, concat, and 35 more.

165 const arrayOfStringArrays: string[][] = map(filter(isNotNil<string>))(arrayOfMaybeStringArrays);
          ~~~~~~~~~~~~~~~~~~~

error TS2345: Argument of type '(string | undefined)[][]' is not assignable to parameter of type 'readonly Dictionary<string | null | undefined>[]'.
  Type '(string | undefined)[]' is not assignable to type 'Dictionary<string | null | undefined>'.
    Index signature for type 'string' is missing in type '(string | undefined)[]'.

165 const arrayOfStringArrays: string[][] = map(filter(isNotNil<string>))(arrayOfMaybeStringArrays);
                                                                          ~~~~~~~~~~~~~~~~~~~~~~~~

If you flip the order of the list and dictionary overrides for filter, like this, then the issue goes away:

export function filter<A, P extends A>(pred: (val: A) => val is P): {
    <B extends A>(dict: Dictionary<B>): Dictionary<P>;
    <B extends A>(list: readonly B[]): P[];
};

If this seems like a reasonable move, I can open a PR, just wanted to get a first impression from someone.

Missing copyright notice

The project is licensed under MIT according to package.json, but it lacks the license text and a copyright notice.

addIndex

Draft branch: https://github.com/ramda/types/tree/addIndex

Current issues

addIndex is particularly unique in terms of type definitions because of how the return type depends on the given function

Let's use filter as an example

// Special case for filter
export function addIndex<T>(
  fn: (f: (item: T) => boolean, list: readonly T[]) => T[],
): _.F.Curry<(a: (item: T, idx: number, list: T[]) => boolean, b: readonly T[]) => T[]>;

To actually use it...

const filterIndexed = addIndex<number>(filter);

filterIndexed(predicate, [1, 2, 3, 4]); // ok
filterIndexed(predicate, ['a', 'b', 'c', 'd']); // error

The problem here is that you have to declare the generic for the type of the Array you intend to use it for. This defeats the purpose of generics in general, however, not passing the generic means that the type is unknown, which means the return type for all use cases is unknown[]

const filterIndexed = addIndex(filter);

filterIndexed(predicate, [1, 2, 3, 4]); // returns `unknown[]`
filterIndexed(predicate, ['a', 'b', 'c', 'd']); // returns `unknown[]`

That at least lets you use filterIndexed for any type, but then you lose all type inference. Not just for the the list, but for the predicate as well

addIndex<string>(filter)(isEven, ['a', 'b', 'c', 'd']); // error on isEven, because `(a: number) => boolean !== (a: string) => boolean`
addIndex(filter)(isEven, ['a', 'b', 'c', 'd']); // no error, because everything here is `unknown`

isEven also needs to be isEven = (item: number, i: number, list: number[]) => boolean otherwise it errors as well. This means that the inner fn type needs to support all overloads

Fix proposals

TODO

What to do about transducers

Transducers are a particularly challenging thing to do in typescript do to how "functions that act as transformers" are isomorphic to them

const a =  [1, 2, 3];

const f = R.compose(
  R.map(R.multiply(2)),
  R.map(R.add(3)),
);

// compose runs the array values through the first map and then the second
f(a); // [5,8,11]

// transduce runs the init transformer into the multiple transformers into the add transformer
R.transduce(f, R.flip(R.append), [], a); // [9, 12, 15]

Now while the above example works fine, once you start transitioning through the types it gets weird quickly

const a =  [1, 2, 3];

// this is completely contrived but gets the point across
const f = R.compose(
  R.map(R.toString()),
  R.map(R.add(3)),
);

f(a); // ['3', '6', '9'];

// because now `toString` is processed first, `add` does string concatenation
R.transduce(f, R.flip(R.append), [], a); // ['13, '23', '33']

Typescript doesn't have "look-ahead" capabilities where it can see where a function is used to determine what its type should be for isomorphic behavior like this

The only way around this that I can think of is to have a separate function for compose and pipe that is typed specifically to the order of operation here

Real world usage of omit is now awkward

I think the types of omit have been strengthened recently as (since minor upgrades to v0.29) I have a number of type errors that are flagged, especially for omit.

If you have a function signature, you may omit certain object keys in the sense, "I'm only interested in a subtype". This allows, say, unit tests to be more minimal and aligns with the principle of least knowledge. But in usage, the omitted keys may be present and you may want to acknowledge this in the implementation.

I'm not sure this is the most minimal example, but I hope shows what I mean:

import R from "ramda";

export interface Params {
    foo: string;
    bar?: string;
}

export function fn1(f: typeof fn2) {
    return (params: Omit<Params, "bar">) => {
        // imagine this omission is an important use case
        return f(R.omit(["bar"] as const, params)); // TS2322
    };
}

function fn2({ foo, bar }: Params): boolean {
    return false;
}

const a: Params = {foo: "foo", bar: "bar"};

fn1(fn2)(a);

See also TS Playground link

In other words, I would expect seemingly unrelated keys not to be a type error. I can probably work around this by creating my own omit implementation, but this goes against the spirit of ramda being a useful multi-tool library when I can't actually use it in a multitude of cases.

I can already hear gnashing of teeth, because probably someone has worked hard to add the new types. Of course, I can see the opposite argument that the strong typing will flag up potential typos.

transduce's accumulator type

I was having an issue with type checker complaining about incompatible input type of accumulator on when trying to use transduce to create function transforming array of values into representation of table rows.

After some investigation, I found what I believe to be a bug in definitions in transduce.d.ts.
When transduce is used as 4-ary and unary function, type V seems to be intended as type of accumulator:

export function transduce<T, U, V>(
  xf: (arg: readonly T[]) => U[],
  fn: (acc: V, val: U) => V,
  acc: V,
  list: readonly T[],
): V;
export function transduce<T, U, V>(
  xf: (arg: readonly T[]) => U[],
): (fn: (acc: V, val: U) => V, acc: V, list: readonly T[]) => V;

but when used as binary and ternary function, accumulator has type readonly T[]:

export function transduce<T, U, V>(
  xf: (arg: readonly T[]) => U[],
  fn: (acc: V, val: U) => V,
): (acc: readonly T[], list: readonly T[]) => V;
export function transduce<T, U, V>(
  xf: (arg: readonly T[]) => U[],
  fn: (acc: V, val: U) => V,
  acc: readonly T[],
): (list: readonly T[]) => V;

Shouldn't they be of type V instead?

Edit: For reference this was on version 0.29.1.

Issues with upgrading from 0.28.25 to 0.29.1 when using yarn PnP

We've recently upgraded from 0.28.25 to 0.29.1 and started having build issues along the lines of

error TS7006: Parameter 'user' implicitly has an 'any' type.

Coming from a function that looks like this (note: a lot of code has been redacted):

export const getUsers = curry(
  async (id: string): Promise<User[]> => {
    // ...
  }
);

// ...

import { getUsers } from '@package/getUsers.js';

// the user param is the one with an implicit any
await getUsers(id)).map(async user => {

As i was looking through the differences, i've noticed that 0.28.25 produces a d.ts which includes a triple slash import

/// <reference types="ts-toolbelt" />
...
getUsers: import("Function/Curry").Curry<(id: string) => Promise<User[]>>;

whereas 0.29.1 does not do that and produces something like below

getUsers: import("ts-toolbelt/out/Function/Curry.js").Curry<(id: string) => Promise<User[]>>;

Installing ts-toolbelt in the project resolves build issues.

@types/ramda failing under 5.4

The types package is currently failing in our nightly run:

Error in ramda
Error: 
/home/runner/work/DefinitelyTyped/DefinitelyTyped/types/ramda/test/allPass-tests.ts
  15:5  error  [email protected] expected type to be:
  (x: number) => boolean
got:
  (a: number) => boolean  @definitelytyped/expect

/home/runner/work/DefinitelyTyped/DefinitelyTyped/types/ramda/test/anyPass-tests.ts
  15:5  error  [email protected] expected type to be:
  (x: number) => boolean
got:
  (a: number) => boolean  @definitelytyped/expect

/home/runner/work/DefinitelyTyped/DefinitelyTyped/types/ramda/test/assoc-tests.ts
  86:20  error  [email protected] compile error: 
This expression is not callable.
  Type 'Record<string, unknown>' has no call signatures                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      @definitelytyped/expect
  86:30  error  [email protected] compile error: 
No overload matches this call.
  Overload 1 of 9, '(...func: [fnLast: (a: any) => Record<string, unknown>, ...func: ((a: any) => any)[], f7: (a: unknown) => unknown, f6: (a: unknown) => unknown, f5: (a: unknown) => unknown, f4: (a: unknown) => unknown, f3: (a: unknown) => unknown, f2: (a: unknown) => unknown, f1: (...args: any[]) => unknown]): (...args: any[]) => Record<string, unknown>', gave the following error.
    Argument of type '{ <K extends string>(prop: K): { <T>(val: T): { <U extends Record<K, T>>(obj: U): U; <U extends Record<K, any>>(obj: U): Record<K, T> & Omit<U, K>; <U>(obj: U): U & Record<...>; }; <U extends Record<...>>(__: Placeholder, obj: U): { ...; }; <U>(__: Placeholder, obj: U): <T>(val: T) => U & Record<...>; <T, U extends ...' is not assignable to parameter of type '(a: any) => Record<string, unknown>'.
      Type '{ <T>(val: T): { <U extends Record<any, T>>(obj: U): U; <U extends Record<any, any>>(obj: U): Record<any, T> & Omit<U, any>; <U>(obj: U): U & Record<...>; }; <U extends Record<...>>(__: Placeholder, obj: U): { ...; }; <U>(__: Placeholder, obj: U): <T>(val: T) => U & Record<...>; <T, U extends Record<...>>(val: T, ob...' is not assignable to type 'Record<string, unknown>'.
        Index signature for type 'string' is missing in type '{ <T>(val: T): { <U extends Record<any, T>>(obj: U): U; <U extends Record<any, any>>(obj: U): Record<any, T> & Omit<U, any>; <U>(obj: U): U & Record<...>; }; <U extends Record<...>>(__: Placeholder, obj: U): { ...; }; <U>(__: Placeholder, obj: U): <T>(val: T) => U & Record<...>; <T, U extends Record<...>>(val: T, ob...'.
  Overload 2 of 9, '(f2: (a: string) => Record<string, unknown>, f1: (val: unknown) => string): (val: unknown) => Record<string, unknown>', gave the following error.
    Argument of type '{ <K extends string>(prop: K): { <T>(val: T): { <U extends Record<K, T>>(obj: U): U; <U extends Record<K, any>>(obj: U): Record<K, T> & Omit<U, K>; <U>(obj: U): U & Record<...>; }; <U extends Record<...>>(__: Placeholder, obj: U): { ...; }; <U>(__: Placeholder, obj: U): <T>(val: T) => U & Record<...>; <T, U extends ...' is not assignable to parameter of type '(a: string) => Record<string, unknown>'.
      Type '{ <T>(val: T): { <U extends Record<any, T>>(obj: U): U; <U extends Record<any, any>>(obj: U): Record<any, T> & Omit<U, any>; <U>(obj: U): U & Record<...>; }; <U extends Record<...>>(__: Placeholder, obj: U): { ...; }; <U>(__: Placeholder, obj: U): <T>(val: T) => U & Record<...>; <T, U extends Record<...>>(val: T, ob...' is not assignable to type 'Record<string, unknown>'  @definitelytyped/expect
  87:20  error  [email protected] compile error: 
This expression is not callable.
  Type 'Record<string, unknown>' has no call signatures                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      @definitelytyped/expect
  87:30  error  [email protected] compile error: 
No overload matches this call.
  Overload 1 of 9, '(...func: [fnLast: (a: any) => Record<string, unknown>, ...func: ((a: any) => any)[], f7: (a: unknown) => unknown, f6: (a: unknown) => unknown, f5: (a: unknown) => unknown, f4: (a: unknown) => unknown, f3: (a: unknown) => unknown, f2: (a: unknown) => unknown, f1: (...args: any[]) => unknown]): (...args: any[]) => Record<string, unknown>', gave the following error.
    Argument of type '{ <K extends string>(prop: K): { <T>(val: T): { <U extends Record<K, T>>(obj: U): U; <U extends Record<K, any>>(obj: U): Record<K, T> & Omit<U, K>; <U>(obj: U): U & Record<...>; }; <U extends Record<...>>(__: Placeholder, obj: U): { ...; }; <U>(__: Placeholder, obj: U): <T>(val: T) => U & Record<...>; <T, U extends ...' is not assignable to parameter of type '(a: any) => Record<string, unknown>'.
  Overload 2 of 9, '(f2: (a: string) => Record<string, unknown>, f1: (val: unknown) => string): (val: unknown) => Record<string, unknown>', gave the following error.
    Argument of type '{ <K extends string>(prop: K): { <T>(val: T): { <U extends Record<K, T>>(obj: U): U; <U extends Record<K, any>>(obj: U): Record<K, T> & Omit<U, K>; <U>(obj: U): U & Record<...>; }; <U extends Record<...>>(__: Placeholder, obj: U): { ...; }; <U>(__: Placeholder, obj: U): <T>(val: T) => U & Record<...>; <T, U extends ...' is not assignable to parameter of type '(a: string) => Record<string, unknown>'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         @definitelytyped/expect

/home/runner/work/DefinitelyTyped/DefinitelyTyped/types/ramda/test/complement-tests.ts
  24:5  error  [email protected] expected type to be:
  (value: any) => value is any
got:
  <T>(value: T) => value is Exclude<T, (null | undefined) & T>  @definitelytyped/expect

/home/runner/work/DefinitelyTyped/DefinitelyTyped/types/ramda/test/filter-tests.ts
  38:14  error  [email protected] compile error: 
No overload matches this call.
  Overload 1 of 5, '(pred: (val: { type: string; }) => val is { type: string; }, list: readonly { type: string; }[]): { type: string; }[]', gave the following error.
    Argument of type '<U extends Partial<Record<"type", any>>>(obj: Required<U> extends Record<"type", any> ? string extends WidenLiterals<U["type"]> ? U : never : never) => boolean' is not assignable to parameter of type '(val: { type: string; }) => val is { type: string; }'.
      Signature '(obj: { type: string; }): boolean' must be a type predicate.
  Overload 2 of 5, '(pred: (val: unknown) => val is unknown, dict: Record<string, unknown>): Record<string, unknown>', gave the following error.
    Argument of type '<U extends Partial<Record<"type", any>>>(obj: Required<U> extends Record<"type", any> ? string extends WidenLiterals<U["type"]> ? U : never : never) => boolean' is not assignable to parameter of type '(val: unknown) => val is unknown'.
      Types of parameters 'obj' and 'val' are incompatible.
        Type 'unknown' is not assignable to type 'Partial<Record<"type", any>>'.
  Overload 3 of 5, '(pred: (value: unknown) => boolean, collection: { type: string; }[]): { type: string; }[]', gave the following error.
    Argument of type '<U extends Partial<Record<"type", any>>>(obj: Required<U> extends Record<"type", any> ? string extends WidenLiterals<U["type"]> ? U : never : never) => boolean' is not assignable to parameter of type '(value: unknown) => boolean'.
      Types of parameters 'obj' and 'value' are incompatible.
        Type 'unknown' is not assignable to type 'Partial<Record<"type", any>>'  @definitelytyped/expect

/home/runner/work/DefinitelyTyped/DefinitelyTyped/types/ramda/test/pick-tests.ts
  23:11  error  [email protected] compile error: 
Type 'Pick<string[], number>' is missing the following properties from type '{ 1: string; 2: string; }': 1, 2           @definitelytyped/expect
  24:11  error  [email protected] compile error: 
Type 'Pick<["a", "b", "c", "d"], number>' is missing the following properties from type '{ 1: "b"; 2: "c"; }': 1, 2     @definitelytyped/expect
  25:11  error  [email protected] compile error: 
Property '0' is missing in type 'Pick<[string, string, string, string], number>' but required in type '{ 0: string; }'  @definitelytyped/expect
  26:11  error  [email protected] compile error: 
Property '0' is missing in type 'Pick<["a", "b", "c", "d"], number>' but required in type '{ 0: "a"; }'                 @definitelytyped/expect
  33:5   error  [email protected] compile error: 
Unused '@ts-expect-error' directive                                                                                     @definitelytyped/expect

/home/runner/work/DefinitelyTyped/DefinitelyTyped/types/ramda/test/propEq-tests.ts
  14:11  error  [email protected] compile error: 
Type '<U extends Partial<Record<5, any>>>(obj: Required<U> extends Record<5, any> ? string extends WidenLiterals<U[5]> ? U : never : never) => boolean' is not assignable to type '(obj: Record<number, string>) => boolean'.
  Types of parameters 'obj' and 'obj' are incompatible.
    Type 'Record<number, string>' is not assignable to type 'never'  @definitelytyped/expect
  43:5   error  [email protected] compile error: 
Unused '@ts-expect-error' directive                                                                                                                                                                                                                                                                                                                        @definitelytyped/expect

✖ 15 problems (15 errors, 0 warnings)

Since the package is not on DT, I'm assuming many of the fixes need to happen here, unless some of these are intentional and should be updated. I haven't seen any specific PRs or issues related to these failures, but happy to be wrong and dedupe this elsewhere.

(The function parameter name thing is an easy fix, but the rest... no clue.)

Github Actions and npm publish

@kedashoe

What do we need to do to get Github Actions set up to either release on merge to main or manually?

The package name is @ramda/type, so I assume we need to set up the correct auth for npm's API to release under that namespace. Starting semver will be 0.1.0. I plan on doing progressive releases of updates so it needs to be separate from ramda's current semver

Let me know. Thanks again!

The Master List

This is the Master list for all the types and the tl;dr for what needs to happen for all

Note: "acts as a transducer" is not something can, nor should, see for more details

Overall things to do:

  • Uniform type names for coming things (eg using T, U, etc)a
  • Idx should be a type Idx = string | number | Symbol and used throughout when constraining anything that is an object key (this will match documentation as well)
  • Ord and Ordering types need to be used more

Functions:

  • add - done
  • addIndex - need to figure out how to automatically infer source function correctly. normalize return type names, needs tests
  • adjust - done
  • all - figure out { all } and how it can work with compose
  • allPass - need to evaluate
  • always - done
  • and - fix tests
  • andThen - needs tests
  • any - needs review
  • anyPass - need to evaluate
  • ap - need to evaluate
  • aperture - need to evaluate
  • append - needs tests
  • apply - needs tests
  • applySpec - could have a better type, look into infering function arity and argument types
  • applyTo - needs tests
  • ascend - needs tests, documentation should be updated to final return Ordering and not Number
  • assoc - needs tests
  • assocPath - needs overloaded types like path, needs tests
  • binary - needs tests
  • bind - needs tests
  • both - look into PredTypeguard variant, needs tests
  • call - needs tests
  • chain - should be good, need to double check, needs tests
  • clamp - need to property curry, constrain T extends Ord, needs tests
  • clone - redo types completely, needs tests
  • collectBy - needs tests
  • comparator - needs tests
  • complement - look into TFiltered variant, needs tests, look into if "can be applied to any functor" needs specific typings
  • compose - re-order, array variant looks wrong, needs tests
  • composeWith - needs overloads, look into AtLeastOneFunctionsFlowFromRightToLeft, needs tests
  • concat - needs tests, needs types for "Dispatches to the concat method", double check currying
  • cond - needs tests
  • construct - needs tests, can improve typing with ConstructorParameters
  • constructN - needs tests, can improve typing with ConstructorParameters
  • converge - needs full investigation, needs tests
  • count - needs tests
  • countBy - look into, needs tests
  • curry - basically a re-export of ts-toolbelt's Curry, not testing because not our responsibility to test another lib's code
  • curryN - doublecheck that it's good
  • dec - done
  • defaultTo - needs tests
  • descend - needs tests
  • difference - needs tests
  • differenceWith - needs tests
  • dissoc - needs tests
  • dissocPath - overload the hell out of it, needs tests
  • divide - currying looks good, needs tests
  • drop - needs tests
  • dropLast - needs tests
  • dropLastWhile - add specific type for handling strings, needs tests
  • dropRepeats - add specific type for handling strings, needs tests
  • dropRepeatsBy - add specific type for handling strings, needs tests
  • dropRepeatsWith - add specific type for handling strings, needs tests
  • dropWhile - add specific type for handling strings, needs tests
  • either - needs tests, types for Applicatives
  • empty - needs test, types for Monoid
  • endsWith - needs tests
  • eqBy - needs tests
  • eqProps - needs tests, the Record constraint variant should be all that is needed
  • equals - needs tests, add specific typings for handing Setoids
  • evolve - look into
  • F - done
  • filter - look into
  • find - look into type narrowing variants, test if those definitions actually do anything, types for "find method"
  • findIndex - needs tests
  • findLast - documents should mention "find method", types to support that, needs tests
  • findLastIndex - needs tests
  • flatten - re-export of ts-toolbelt's
  • flip - look into
  • forEach - done!
  • forEachObjIndexed - needs tests
  • fromPairs - needs tests, look into
  • groupBy - types for "groupBy method" variant, needs tests
  • groupWith - full currying, better string support, needs tests
  • gt - full currying, switch to T extends Ord, needs tests
  • gte - full currying, switch to T extends Ord, needs tests, fantasy-land Ord support?
  • has - better typing for inference, needs tests, look into ObjectHavingSome
  • hasIn - full currying, needs tests
  • hasPath - full currying, needs tests
  • head - fix T extends any (can be just T), needs tests
  • identical - needs tests
  • identity - done
  • ifElse - should infer returns, needs tests
  • inc - done
  • includes - readonly string[] | string doesn't seem right, needs tests
  • indexBy - look into, needs tests
  • indexOf - string[] | string doesn't seem right, needs tests
  • init - needs tests
  • innerJoin - curry, needs tests
  • insert - curry, needs tests
  • insertAll - curry, needs tests
  • intersection - done
  • intersperse - handle "intersperse method", needs tests
  • into - very wrong, redo completely
  • invert - although non Idx types are automatically coerced into string, should the typings for this limit the object values to be Idx for practical purposes? it would be practical as this function doesn't hold much value for objects with values that aren't Idx (eg, anon-funcs and objects, the later coerced to '[object Object]')
  • invertObj - same as above
  • invoker - typescript can be used to infer things if desired
  • is - needs tests
  • isEmpty - needs tests
  • isNil - needs tests
  • isNotNil - needs tests (also this is not on 0.28.0, it's new)
  • join - needs tests
  • juxt - need to review
  • keys - needs tests
  • keysIn - return type should be Idx[]
  • last - needs review of populated array overload
  • lastIndexOf - review readonly string[] | string of string overload
  • length - docs say that arg should be an array, type is for any object that has length prop, need to confirm if that is the intent
  • lens - need to confirm defined types
  • lensIndex - same
  • lensPath - need to work out path arity overloads
  • lensProp - same
  • lift - needs full review
  • liftN - needs full review
  • lt - should be typed with Ord
  • lte - should be typed with Ord
  • map - need to review Functor,
  • mapAccum - need to curry, need tests
  • mapAccumRight - need to curry, need tests
  • mapObjIndexed - need full review
  • match - need to curry, need tests
  • mathMod - need tests
  • max - need tests
  • maxBy - better currying, need tests
  • mean - tests? (no real value in test)
  • median - tests? (no real value in test)
  • memoizeWith - needs review, doesn't look right
  • mergeAll - review MergeAll
  • mergeDeepLeft - needs tests
  • mergeDeepRight - needs tests
  • mergeDeepWith - needs to be completely redone
  • mergeDeepWithKey - needs to be completely redone
  • mergeLeft - need tests
  • mergeRight - need tests
  • mergeWith- needs to be completely redone
  • mergeWithKey- needs to be completely redone
  • min - need tests
  • minBy - better currying, tests
  • modify - needs review, needs tests
  • modulo - need tests
  • move - double-check currying order, need tests
  • multiply - need tests
  • nAry - needs review
  • negate - tests? (no real value)
  • none - currying, tests, handle "method all" variant
  • not - test? (no real value)
  • nth - needs tests
  • nthArg - could do a lot better, need to look into
  • o - review currying, tests
  • objOf - currying, tests
  • of - test? (no real value)
  • omit - currying, tests
  • on - currying ordering needs to be reversed, type names could be better, tests
  • once - needs tests
  • or - usage of Falsy doesn't really apply in typings, review and add currying
  • otherwise - currying, tests
  • over - currying, tests
  • pair - currying, tests
  • partial - types cover arity 2 to 4, could do more, or find a fully automated way, return func should not be curried
  • partialObject - needs full review
  • partialRight - needs full review
  • partition - string[] variety serves no purpose, curry and test
  • path - currying, tests
  • pathEq - needs to be overloaded like path, currying, tests
  • pathOr - needs to be overloaded like path, currying, tests
  • paths - will be extremely hard to overload, probably should just leave in it's most basic form, needs curry and test
  • pathSatisfies - needs to be overloaded like path, currying, tests
  • pick - K[] should be K keyof U, since properties that don't exist are ignored, it makes no sense to constrain this to only known keys. Return value Pick<> can be used directly in this case
  • pickAll - needs full review
  • pickBy - since returned keys are unknown at build time, return type should be just Partial<U>. Curry and Test
  • pipe - spread variety needs to be fixed, tests
  • pipeWith - needs full review
  • pluck - needs review, most of the overloads are redundant, need to add Functor support
  • prepend - currying, tests
  • product - test? (no real value)
  • project - can be redone using Pick<>, curry and test
  • promap - support obj.promap variety, curry and test
  • prop - needs tests
  • propEq - currying, tests
  • propIs - typing is very wrong, needs to be completely redo
  • propOr - docs should say Idx, not String for key, typing should be K keyof U, needs curing and tests
  • props - look into better way to type this
  • propSatisfies - needs review, curry and test
  • range - curry and test
  • reduce - curry and test
  • reduceBy - curry and test
  • reduced - test? (no real value)
  • reduceRight - needs Reduced<T> to return value of reducer func, curry and test
  • reduceWhile - needs Reduced<T> to return value of reducer func, curry and test
  • reject - needs full revue
  • remove - curry and test
  • repeat - curry and test
  • replace - curry and test
  • reverse - test? (no real value)
  • scan - fix reduce function return type, currying and test
  • set - curry and test
  • sequence - MISSING
  • slice - curry and test, handle "slice method" variant
  • sort - curry and test, fn return type should be Ordering
  • sortBy - curry and test
  • sortWith - curry and test, fn return type should be Ordering
  • split - curry and test
  • splitAt - curry and test
  • splitEvery - curry and test
  • splitWhen - curry and test
  • splitWhenever - curry and test
  • startsWith - curry and test
  • subtract - curry and test
  • sum -test? (no real value)
  • symmetricDifference - curry and test
  • symmetricDifferenceWith - curry and test
  • T - test? (no real value)
  • tail - extends any in unnecessary, curry and test
  • take - take<T>(n: number): (xs: readonly T[]) => T[] overload should be removed, curry and test, handle "take method" variation
  • takeLast - tests
  • takeLastWhile - curry and test
  • takeWhile - curry and test
  • tap - asserts a is R overload is completely wrong, curry and test
  • test - curry and test
  • thunkify - test? (no real value)
  • times - curring and tests
  • toLower - tests
  • toPairs - need to review
  • toPairsIn - need to review
  • toString - test? (no real value)
  • toUpper - tests
  • transduce - need to review
  • transpose - test? (no real value)
  • traverse - handle "traverse method" variant, and review in general
  • trim - test? (no real value)
  • tryCatch - need to review
  • type - test? (no real value)
  • unapply - can infer typing for input function's array argument, tests
  • unary - test
  • uncurryN - need to review
  • unfold - curry and test
  • union - curry and test
  • unionWith - curry and test
  • uniq - test? (no real value)
  • uniqBy - curry and test
  • uniqWith - look into why there is a U in the generic, curry and test
  • unless - curry and test
  • unnest - since is the same as chain(identity) need to handle "chain method" variant. curry and test
  • until - curry and test
  • unwind - MISSING
  • update - curry and test
  • useWith - needs full review
  • values - need to test ValueOfUnion,
  • valuesIn - there is zero inference, that may be the way it should be, needs review
  • view - curry and test
  • when - need to review
  • where - would make sense to constrain testObj to defined keys of spec, curry and test
  • whereAny - MISSING
  • whereEq - same issues as where
  • without - curry and test
  • xor - curry and test
  • xprod - likely cannot restrict bs to have same length as as, curry and test
  • zip - curry and test
  • zipObj - curry and test
  • zipWith - curry and test

Clean up `tools.d.ts`

There are a lot of extra, unused, deprecated, and useless type alias' in tools.d.ts

This issue to clean it up

  • TODO

Why is `ElementOf` so complex?

What benefit does ElementOf<T> have over T[number]? The conditional type and use of infer are potentially far more expensive than is necessary.

Call signature of `take` can prevent type inferrence when using curried signature

The current typing of the take function is this:

export function take(n: number): {
  (xs: string): string;
  <T>(xs: readonly T[]): T[];
};
export function take(n: number, xs: string): string;
export function take<T>(n: number, xs: readonly T[]): T[];

Right now, when you call the curried signature inside a pipe, the type of the array is not correctly inferred:

image You can see the type inference is working correctly without the `R.take` call: image

The solution is to change the curried signature for taking from an array to this:

export function take<T>(n:number): (xs: readonly T[]) => T[]

This also applies to takeLast.

I would be happy to open a PR for this.

Breaking change introduced

Hi - looks like this commit broke these types: 3f8e31d

[!] (plugin typescript) RollupError: @rollup/plugin-typescript TS1139: Type parameter declaration expected.
../../../../node_modules/@types/ramda/node_modules/types-ramda/es/index.d.ts (4453:22)
4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;

Type inference on ifElse

Hello , just wanted to leave this here, the type inference of the ifElse function seems to not be working in this case:

image

Bests!

How to type curried functions

ramda's curry function is awesome but also has abilities that are not strictly necessary to type

// all of these work!
R.divide(10, 2); // 5
R.divide()(10, 2); // 5
R.divide(R.__)(10, 2); // 5

The use cases for both R.divide() and R.divide(R.__) are however negligible

So when typing out, we're only going to type it as:

export function divide(a: number, b: number): number;
export function divide(__: Placeholder, b: number): (a: number) => number;
export function divide(a: number): (b: number) => number;

And leave out

export function divide(): (a: number, b: number) => number;
export function divide(__: Placeholder): (a: number, b: number) => number;

Make `isNotNil` a type guard

Currently if you use isNotNil to filter an array of type (T | undefined | null)[], the result will have the same type.

If, instead, we would define isNotNil as follows:

export const isNotNil = <T>(value?: T): value is Exclude<T, null | undefined> => value != null

we could do something like

const example = [1, 23, null, 5, undefined].filter(isNotNil) // typed as `number[]`

Symbol type is not filtered out of keys in types for fromPairs, keys, toPairs, and toPairsIn

Problem

#50 incorrectly altered the original types for fromPairs, keys, toPairs and toPairsIn.

The implementation of these functions filter out symbol keys via for ... in or Object.keys. The original types captured this fact. The altered types do not. This has implications for operations that work with the outputs of these functions that expect symbol key types to be excluded.

Sandbox Demo: https://stackblitz.com/edit/vitejs-vite-tqnrhv?file=src%2Framda-demo.ts&terminal=dev

Implementation References

Automate release

Currently, I'm just using npm publish on my local machine. I'd much rather move to a gitflow style with develop and main branch. semantic-release I like a lot, as it gives us great control of automatic semver bumps and Github release info

Open to other suggestions as well. I just want to define what that process should be and come up with a good strategy in general

`of` now receives two parameters instead of one

From the v0.29 upgrade guide:
... improve of to work with more Applicative types. of now receives two parameters instead of one: the first parameter is type Constructor, and the second parameter is the value to be wrapped

The current typings do not yet reflect this change: export function of<T>(x: T): T[];

mergeAll does not accept arrays anymore

Hi and thank you for the ramda!

We just upgraded to 0.29.0 and the following code does not type check

import {mergeAll} from 'ramda';

const list: Array<{x: number}> = [{x: 1}, {x: 2}];
const result = mergeAll(list);

It fails with Argument of type '{ x: number; }[]' is not assignable to parameter of type '[{ x: number; }, ...{ x: number; }[]]'. Source provides no match for required element at position 0 in target.

Have to do something like

const list: Array<{x: number}> = [{x: 1}, {x: 2}];
const result = mergeAll([list[0], ...list]);

to make it work. The js code works with passing in arrays. I this intended?

`pluck` does not work with argument typed as `any`

Summary

When pluck is called with a final argument typed as any, it results in a TypeScript error.

I'm not sure if this is actually an error or desired behavior. Casting the argument to any[] resolves the type error. I would expect any to be allowed since it can be a list, but perhaps that is not the intention of this lib. Of course, if this is desired behavior, please close

Dependencies

Example

import { pluck } from "ramda";

const array = [{ id: 1 }, { id: 2 }] as any;

pluck("id", array);
      ^^^^

Error message (snippet)

No overload matches this call.
  Overload 1 of 4, '(p: never, list: readonly unknown[]): never[]', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'never'.
  Overload 2 of 4, '(p: number, list: { [k: number]: unknown; }[]): unknown[]', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'number'.

/types-ramda/es/index.d.ts:4453:22 - error

i just updated my project now its full of type errors from this package. I dont even call this package so it is a dependancy of a dependancy... oh joy

do you guys plan to update or rollback your package to fix this please?

yarn compile --fix
yarn run v1.22.19
$ tsc --noEmit && eslint --max-warnings 0 src --fix
node_modules/types-ramda/es/index.d.ts:4453:22 - error TS1139: Type parameter declaration expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                          ~~~~~

node_modules/types-ramda/es/index.d.ts:4453:34 - error TS1005: ',' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                      ~~~~~~~

node_modules/types-ramda/es/index.d.ts:4453:51 - error TS1005: ',' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                       ~

node_modules/types-ramda/es/index.d.ts:4453:79 - error TS1005: ',' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                   ~

node_modules/types-ramda/es/index.d.ts:4453:82 - error TS1005: ',' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                      ~

node_modules/types-ramda/es/index.d.ts:4453:89 - error TS1005: ')' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                             ~

node_modules/types-ramda/es/index.d.ts:4453:91 - error TS1434: Unexpected keyword or identifier.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                               ~~~~~

node_modules/types-ramda/es/index.d.ts:4453:96 - error TS1128: Declaration or statement expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                    ~

node_modules/types-ramda/es/index.d.ts:4453:97 - error TS1128: Declaration or statement expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                     ~

node_modules/types-ramda/es/index.d.ts:4453:159 - error TS1005: ';' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                                                                                   ~~~~~~~

node_modules/types-ramda/es/index.d.ts:4453:167 - error TS1434: Unexpected keyword or identifier.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                                                                                           ~~~~~

node_modules/types-ramda/es/index.d.ts:4454:25 - error TS1139: Type parameter declaration expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                             ~~~~~

node_modules/types-ramda/es/index.d.ts:4454:37 - error TS1005: ',' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                         ~~~~~~~

node_modules/types-ramda/es/index.d.ts:4454:54 - error TS1005: ',' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                          ~

node_modules/types-ramda/es/index.d.ts:4454:61 - error TS1005: ',' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                 ~

node_modules/types-ramda/es/index.d.ts:4454:67 - error TS1003: Identifier expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                       ~

node_modules/types-ramda/es/index.d.ts:4454:74 - error TS1005: ')' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                              ~

node_modules/types-ramda/es/index.d.ts:4454:75 - error TS1128: Declaration or statement expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                               ~

node_modules/types-ramda/es/index.d.ts:4454:78 - error TS1005: ';' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                  ~

node_modules/types-ramda/es/index.d.ts:4454:79 - error TS1109: Expression expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                   ~

node_modules/types-ramda/es/index.d.ts:4454:86 - error TS1005: ')' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                          ~

node_modules/types-ramda/es/index.d.ts:4454:98 - error TS1005: ';' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                      ~

node_modules/types-ramda/es/index.d.ts:4454:100 - error TS1434: Unexpected keyword or identifier.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                        ~

node_modules/types-ramda/es/index.d.ts:4454:101 - error TS1128: Declaration or statement expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                         ~

node_modules/types-ramda/es/index.d.ts:4454:102 - error TS1128: Declaration or statement expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                          ~

node_modules/types-ramda/es/index.d.ts:4454:104 - error TS1434: Unexpected keyword or identifier.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                            ~~~~~~

node_modules/types-ramda/es/index.d.ts:4454:111 - error TS1128: Declaration or statement expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                                   ~~~~~~~

node_modules/types-ramda/es/index.d.ts:4454:119 - error TS1434: Unexpected keyword or identifier.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                                           ~~~~~


Found 28 errors in the same file, starting at: node_modules/types-ramda/es/index.d.ts:4453

error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
➜  moralis-admin-frontend git:(feat-streams-additional-data-step) ✗ yarn compile --fix
yarn run v1.22.19
$ tsc --noEmit && eslint --max-warnings 0 src --fix
node_modules/types-ramda/es/index.d.ts:4453:22 - error TS1139: Type parameter declaration expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                          ~~~~~

node_modules/types-ramda/es/index.d.ts:4453:34 - error TS1005: ',' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                      ~~~~~~~

node_modules/types-ramda/es/index.d.ts:4453:51 - error TS1005: ',' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                       ~

node_modules/types-ramda/es/index.d.ts:4453:79 - error TS1005: ',' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                   ~

node_modules/types-ramda/es/index.d.ts:4453:82 - error TS1005: ',' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                      ~

node_modules/types-ramda/es/index.d.ts:4453:89 - error TS1005: ')' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                             ~

node_modules/types-ramda/es/index.d.ts:4453:91 - error TS1434: Unexpected keyword or identifier.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                               ~~~~~

node_modules/types-ramda/es/index.d.ts:4453:96 - error TS1128: Declaration or statement expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                    ~

node_modules/types-ramda/es/index.d.ts:4453:97 - error TS1128: Declaration or statement expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                     ~

node_modules/types-ramda/es/index.d.ts:4453:159 - error TS1005: ';' expected.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                                                                                   ~~~~~~~

node_modules/types-ramda/es/index.d.ts:4453:167 - error TS1434: Unexpected keyword or identifier.

4453 export function pick<const Names extends readonly [PropertyKey, ...PropertyKey[]]>(names: Names): <U extends Record<ElementOf<Names>, any>>(obj: U) => string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                                                                                           ~~~~~

node_modules/types-ramda/es/index.d.ts:4454:25 - error TS1139: Type parameter declaration expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                             ~~~~~

node_modules/types-ramda/es/index.d.ts:4454:37 - error TS1005: ',' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                         ~~~~~~~

node_modules/types-ramda/es/index.d.ts:4454:54 - error TS1005: ',' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                          ~

node_modules/types-ramda/es/index.d.ts:4454:61 - error TS1005: ',' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                 ~

node_modules/types-ramda/es/index.d.ts:4454:67 - error TS1003: Identifier expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                       ~

node_modules/types-ramda/es/index.d.ts:4454:74 - error TS1005: ')' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                              ~

node_modules/types-ramda/es/index.d.ts:4454:75 - error TS1128: Declaration or statement expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                               ~

node_modules/types-ramda/es/index.d.ts:4454:78 - error TS1005: ';' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                  ~

node_modules/types-ramda/es/index.d.ts:4454:79 - error TS1109: Expression expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                   ~

node_modules/types-ramda/es/index.d.ts:4454:86 - error TS1005: ')' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                          ~

node_modules/types-ramda/es/index.d.ts:4454:98 - error TS1005: ';' expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                      ~

node_modules/types-ramda/es/index.d.ts:4454:100 - error TS1434: Unexpected keyword or identifier.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                        ~

node_modules/types-ramda/es/index.d.ts:4454:101 - error TS1128: Declaration or statement expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                         ~

node_modules/types-ramda/es/index.d.ts:4454:102 - error TS1128: Declaration or statement expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                          ~

node_modules/types-ramda/es/index.d.ts:4454:104 - error TS1434: Unexpected keyword or identifier.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                            ~~~~~~

node_modules/types-ramda/es/index.d.ts:4454:111 - error TS1128: Declaration or statement expected.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                                   ~~~~~~~

node_modules/types-ramda/es/index.d.ts:4454:119 - error TS1434: Unexpected keyword or identifier.

4454 export function pick<U, const Names extends readonly [keyof U, ...(keyof U)[]]>(names: Names, obj: U): string extends keyof U ? Record<string, U[keyof U]> : Pick<U, ElementOf<Names>>;
                                                                                                                           ~~~~~


Found 28 errors in the same file, starting at: node_modules/types-ramda/es/index.d.ts:4453

groupBy returns a type that is not compatible with Object.entries

Given the following groupBy invocation using version 0.29.10 of types

const messagesByGroupId = groupBy(
  message => message.groupId,
  messages,
);

when using entries and strict like so

for (const [groupId, messages] of Object.entries(messagesByGroupId)) {
  // messages might be undefined
}

the messages variable type is T[] | undefined forcing us to do an extra check, but it shouldn't be possible for it to be undefined since we're iterating over object properties.

This PR introduces the change - #45 that leads to the possible undefined.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.