Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Issue 110 object map keys #111

Merged
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"name": "typescript-ramda",
"version": "0.21.0",
"scripts": {
"test": "tsc --module amd ramda-tests.ts"
"test": "tsc --module amd ramda-tests.ts"
},
"devDependencies": {
"ramda": "0.21.0",
"typescript": "^1.8.10"
"typescript": "^2.0.10"
}
}
19 changes: 11 additions & 8 deletions ramda-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class F2 {
R.propIs(Number)('x', {x: 1, y: 2}); //=> true
R.propIs(Number)('x')({x: 1, y: 2}); //=> true
R.propIs(Number, 'x', {x: 'foo'}); //=> false
R.propIs(Number, 'x', {}); //=> false
// v errors with `Argument of type '"x"' is not assignable to parameter of type 'never'.`, because 'x' is not in `{}`.
// R.propIs(Number, 'x', {}); //=> false
});

(() => {
Expand Down Expand Up @@ -597,9 +598,9 @@ interface Obj { a: number; b: number };

(() => {
let list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}];
const a1 = R.indexBy(R.prop<string>('id'), list);
const a2 = R.indexBy(R.prop<string>('id'))(list);
const a3 = R.indexBy<{id:string}>(R.prop<string>('id'))(list);
const a1 = R.indexBy(R.prop('id'), list);
const a2 = R.indexBy(R.prop('id'))(list);
const a3 = R.indexBy<{id:string}>(R.prop('id'))(list);
});

() => {
Expand Down Expand Up @@ -1306,9 +1307,10 @@ class Rectangle {

() => {
const a1 = R.pick(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1, d: 4}
const a2 = R.pick<any, {a: number}>(['a', 'e', 'f'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1}
const a3 = R.pick(['a', 'e', 'f'])({a: 1, b: 2, c: 3, d: 4}); //=> {a: 1}
const a4 = R.pick(['a', 'e', 'f'], [1, 2, 3, 4]); //=> {a: 1}
// the following should errror: e/f are not keys in these objects
// const a2 = R.pick(['a', 'e', 'f'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1}
// const a3 = R.pick(['a', 'e', 'f'])({a: 1, b: 2, c: 3, d: 4}); //=> {a: 1}
// const a4 = R.pick(['a', 'e', 'f'], [1, 2, 3, 4]); //=> {a: 1}
}

() => {
Expand Down Expand Up @@ -1362,7 +1364,8 @@ matchPhrases(['foo', 'bar', 'baz']);

() => {
var x: number = <number>R.prop('x', {x: 100}); //=> 100
const a = R.prop('x', {}); //=> undefined
// errors: `Argument of type '"x"' is not assignable to parameter of type 'never'.` cuz no 'x' in {}
// const a = R.prop('x', {}); //=> undefined
}

() => {
Expand Down
117 changes: 62 additions & 55 deletions ramda.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ declare var R: R.Static;

declare namespace R {
type Ord = number | string | boolean;
type Prop = string | number;
type Path = Prop[];

interface ListIterator<T, TResult> {
(value: T, index: number, list: T[]): TResult;
Expand Down Expand Up @@ -39,11 +41,11 @@ declare namespace R {
}

interface ObjFunc {
[index:string]: Function;
[index: string]: Function;
}

interface ObjFunc2 {
[index:string]: (x: any, y: any) => boolean;
[index: string]: (x: any, y: any) => boolean;
}

interface Pred {
Expand Down Expand Up @@ -210,18 +212,18 @@ declare namespace R {
/**
* Makes a shallow clone of an object, setting or overriding the specified property with the given value.
*/
assoc<T,U>(prop: string, val: T, obj: U): {prop: T} & U;
assoc(prop: string): <T,U>(val: T, obj: U) => {prop: T} & U;
assoc<T>(prop: string, val: T): <U>(obj: U) => {prop: T} & U;
assoc<T,U>(prop: Prop, val: T, obj: U): {prop: T} & U;
assoc(prop: Prop): <T,U>(val: T, obj: U) => {prop: T} & U;
assoc<T>(prop: Prop, val: T): <U>(obj: U) => {prop: T} & U;


/**
* Makes a shallow clone of an object, setting or overriding the nodes required to create the given path, and
* placing the specific value at the tail end of that path.
*/
assocPath<T,U>(path: string[], val: T, obj: U): U;
assocPath(path: string[]): <T,U>(val: T, obj: U) => U;
assocPath<T>(path: string[], val: T): <U>(obj: U) => U;
assocPath<T,U>(path: Path, val: T, obj: U): U;
assocPath(path: Path): <T,U>(val: T, obj: U) => U;
assocPath<T>(path: Path, val: T): <U>(obj: U) => U;

/**
* Wraps a function of any arity (including nullary) in a function that accepts exactly 2
Expand Down Expand Up @@ -430,14 +432,14 @@ declare namespace R {
* Returns a new object that does not contain a prop property.
*/
// It seems impossible to infer the return type, so this may to be specified explicitely
dissoc<T>(prop: string, obj: any): T;
dissoc(prop: string): <U>(obj: any) => U;
dissoc<T>(prop: Prop, obj: any): T;
dissoc(prop: Prop): <U>(obj: any) => U;

/**
* Makes a shallow clone of an object, omitting the property at the given path.
*/
dissocPath<T>(path: string[], obj: any): T;
dissocPath(path: string[]): <T>(obj: any) => T;
dissocPath<T>(path: Path, obj: any): T;
dissocPath(path: Path): <T>(obj: any) => T;

/**
* Divides two numbers. Equivalent to a / b.
Expand Down Expand Up @@ -505,10 +507,10 @@ declare namespace R {
/**
* Reports whether two functions have the same value for the specified property.
*/
eqProps<T,U>(prop: string, obj1: T, obj2: U): boolean;
eqProps<T,U>(prop: string): CurriedFunction2<T,U,boolean>;
eqProps(prop: string): <T,U>(obj1: T, obj2: U) => boolean;
eqProps<T>(prop: string, obj1: T): <U>(obj2: U) => boolean;
eqProps<T,U>(prop: Prop, obj1: T, obj2: U): boolean;
eqProps<T,U>(prop: Prop): CurriedFunction2<T,U,boolean>;
eqProps(prop: Prop): <T,U>(obj1: T, obj2: U) => boolean;
eqProps<T>(prop: Prop, obj1: T): <U>(obj2: U) => boolean;

/**
* Returns true if its arguments are equivalent, false otherwise. Dispatches to an equals method if present.
Expand All @@ -522,10 +524,11 @@ declare namespace R {
*/
evolve<V>(transformations: Nested<V>, obj: V): Nested<V>;
evolve<V>(transformations: Nested<V>): <V>(obj: V) => Nested<V>;

/*
* A function that always returns false. Any passed in parameters are ignored.
*/
F(): boolean;
F(): false;

/**
* Returns a new list containing only those items that match a given predicate function. The predicate function is passed one argument: (value).
Expand Down Expand Up @@ -586,8 +589,7 @@ declare namespace R {
/**
* Creates a new object out of a list key-value pairs.
*/
fromPairs<V>(pairs: KeyValuePair<string, V>[]): {[index: string]: V};
fromPairs<V>(pairs: KeyValuePair<number, V>[]): {[index: number]: V};
fromPairs<V>(pairs: KeyValuePair<Prop, V>[]): {[index: string]: V};

/**
* Splits a list into sublists stored in an object, based on the result of
Expand Down Expand Up @@ -633,7 +635,7 @@ declare namespace R {
* Returns the first element in a list.
* In some libraries this function is named `first`.
*/
head<T>(list: T[]): T;
head<T extends Array<any>>(list: T): T[0];
head(list: string): string;

/**
Expand Down Expand Up @@ -738,14 +740,14 @@ declare namespace R {
/**
* Same as R.invertObj, however this accounts for objects with duplicate values by putting the values into an array.
*/
invert<T>(obj: T): {[index:string]: string[]};
invert<T>(obj: T): {[index: string]: string[]};
invert<T>(obj: T): {[index: number]: string[]};

/**
* Returns a new object with the keys of the given object as values, and the values of the given object as keys.
*/
invertObj(obj: any): {[index:string]: string};
invertObj(obj: {[index: number]: string}): {[index:string]: string};

invertObj(obj: {[index: string]: Prop}): {[index: string]: string};
invertObj(obj: {[index: number]: Prop}): {[index: string]: string};

/**
* Turns a named method of an object (or object prototype) into a function that can be
Expand All @@ -762,8 +764,8 @@ declare namespace R {
* See if an object (`val`) is an instance of the supplied constructor.
* This function will check up the inheritance chain, if any.
*/
is(ctor: any, val: any): boolean;
is(ctor: any): (val: any) => boolean;
is<T>(ctor: T, val: any): val is T;
is<T>(ctor: T): (val: any) => val is T;

/**
* Tests whether or not an object is similar to an array.
Expand Down Expand Up @@ -888,9 +890,10 @@ declare namespace R {
* Returns a new list, constructed by applying the supplied function to every element of the supplied list.
*/
map<T, U>(fn: (x: T) => U, list: T[]): U[];
map<T, U>(fn: (x: T) => U, obj: U): U;
map<T, U>(fn: (x: T) => U, obj: Functor<T>): Functor<U>; // used in functors
map<T, U>(fn: (x: T) => U): (list: T[]) => U[];
map<T, V, M extends {[k: string]: T}>(fn: (value: T) => V, obj: M): {[K in keyof M]: V};
map<T, V, M extends {[k: string]: T}>(fn: (value: T) => V): (obj: M) => {[K in keyof M]: V};
map<T, U>(fn: (x: T) => U, obj: Functor<T>): Functor<U>; // used in functors

/**
* The mapAccum function behaves like a combination of map and reduce.
Expand All @@ -910,12 +913,8 @@ declare namespace R {
/**
* Like mapObj, but but passes additional arguments to the predicate function.
*/
mapObjIndexed<T, TResult>(fn: (value: T, key: string, obj?: { [index: string]: T }) =>
TResult, obj: { [index: string]: T }): { [index: string]: TResult };
mapObjIndexed<T, TResult>(fn: (value: T, key: string, obj?: any) => TResult, obj: any): {[index:string]: TResult};
mapObjIndexed<T, TResult>(fn: (value: T, key: string, obj?: { [index: string]: T }) =>
TResult): (obj: { [index: string]: T }) => { [index: string]: TResult };
mapObjIndexed<T, TResult>(fn: (value: T, key: string, obj?: any) => TResult): (obj: any) => {[index:string]: TResult};
mapObjIndexed<T, V, M extends {[k: string]: T}>(fn: (value: T, key: string, obj?: M) => V, obj: M): {[K in keyof M]: V};
mapObjIndexed<T, V, M extends {[k: string]: T}>(fn: (value: T, key: string, obj?: M) => V): (obj: M) => {[K in keyof M]: V};

/**
* Tests a regular expression agains a String
Expand Down Expand Up @@ -1173,22 +1172,22 @@ declare namespace R {
* Returns a partial copy of an object containing only the keys specified. If the key does not exist, the
* property is ignored.
*/
pick<T,U>(names: string[], obj: T): U;
pick(names: string[]): <T, U>(obj: T) => U;
pick<T, K extends keyof T>(names: K[], obj: T): Pick<T, K>;
pick<T, K extends keyof T>(names: K[]): (obj: T) => Pick<T, K>;


/**
* Similar to `pick` except that this one includes a `key: undefined` pair for properties that don't exist.
*/
pickAll<T,U>(names: string[], obj: T): U;
pickAll(names: string[]): <T,U>(obj: T) => U;
pickAll<T, K>(names: K[], obj: T): Partial<T>;
pickAll<T, K>(names: K[]): (obj: T) => Partial<T>;


/**
* Returns a partial copy of an object containing only the keys that satisfy the supplied predicate.
*/
pickBy<T,U>(pred: ObjPred, obj: T): U;
pickBy(pred: ObjPred): <T,U>(obj: T) => U;
pickBy<T>(pred: ObjPred, obj: T): Partial<T>;
pickBy(pred: ObjPred): <T>(obj: T) => Partial<T>;


/**
Expand Down Expand Up @@ -1258,15 +1257,17 @@ declare namespace R {
* Returns a function that when supplied an object returns the indicated property of that object, if it exists.
* Note: TS1.9 # replace any by dictionary
*/
prop<T>(p: string, obj: any): T;
prop<T>(p: string): <T>(obj: any) => T;
prop<T, K extends keyof T>(p: K, obj: T): T[K];
// prop<T, K extends keyof T>(p: K): (obj: T) => T[K];
prop<K extends Prop>(p: K): <T, K extends keyof T>(obj: T) => T[K]; // are these Ks bound properly?
// prop(p: Prop): (obj: any) => any;

/**
* Determines whether the given property of an object has a specific
* value according to strict equality (`===`). Most likely used to
* filter a list.
*/
// propEq<T>(name: string, val: T, obj: {[index:string]: T}): boolean;
// propEq<T>(name: string, val: T, obj: {[index: Prop]: T}): boolean;
// propEq<T>(name: string, val: T, obj: {[index:number]: T}): boolean;
propEq<T>(name: string, val: T, obj: any): boolean;
propEq<T>(name: string, val: T): (obj: any) => boolean;
Expand All @@ -1277,12 +1278,18 @@ declare namespace R {
/**
* Returns true if the specified object property is of the given type; false otherwise.
*/
propIs(type: any, name: string, obj: any): boolean;
propIs(type: any, name: string): (obj: any) => boolean;
propIs(type: any): CurriedFunction2<string, any, boolean>;
propIs<T, V, K extends keyof V>(type: T, name: K, obj: V): obj is (V & Record<K, T>)
// v object info not available in time :(
// propIs<T, V, K extends keyof V>(type: T, name: K): (obj: V) => obj is (V & Record<K, T>)
// propIs<T, V, K extends keyof V>(type: T): {
// (name: K, obj: V): obj is (V & Record<K, T>);
// (name: K): (obj: V) => obj is (V & Record<K, T>);
// }
propIs(type: any, name: Prop): (obj: any) => boolean;
propIs(type: any): CurriedFunction2<Prop, any, boolean>;
propIs(type: any): {
(name: string, obj: any): boolean;
(name: string): (obj: any) => boolean;
(name: Prop, obj: any): boolean;
(name: Prop): (obj: any) => boolean;
}

/**
Expand All @@ -1298,8 +1305,8 @@ declare namespace R {
* The only difference from `prop` is the parameter order.
* Note: TS1.9 # replace any by dictionary
*/
props<T>(ps: string[], obj: any): T[];
props(ps: string[]): <T>(obj: any) => T[];
props<T>(ps: Path, obj: any): T[];
props(ps: Path): <T>(obj: any) => T[];

/**
* Returns true if the specified object property satisfies the given predicate; false otherwise.
Expand Down Expand Up @@ -1485,7 +1492,7 @@ declare namespace R {
/**
* A function that always returns true. Any passed in parameters are ignored.
*/
T(): boolean;
T(): true;

/**
* Returns all but the first element of a list.
Expand Down Expand Up @@ -1563,15 +1570,15 @@ declare namespace R {
* Note that the order of the output array is not guaranteed to be
* consistent across different JS platforms.
*/
toPairs<F,S>(obj: {[k: string]: S} | {[k: number]: S} | any): [F,S][];
toPairs<F,S>(obj: {[k: string]: S} | any): [F,S][];

/**
* Converts an object into an array of key, value arrays.
* The object's own properties and prototype properties are used.
* Note that the order of the output array is not guaranteed to be
* consistent across different JS platforms.
*/
toPairsIn<F,S>(obj: {[k: string]: S} | {[k: number]: S} | any): [F,S][];
toPairsIn<F,S>(obj: {[k: string]: S} | any): [F,S][];

/**
* Returns the string representation of the given value. eval'ing the output should
Expand Down Expand Up @@ -1815,8 +1822,8 @@ declare namespace R {
* Creates a new object out of a list of keys and a list of values.
*/
// TODO: Dictionary<T> as a return value is to specific, any seems to loose
zipObj<T>(keys: string[], values: T[]): {[index:string]: T};
zipObj(keys: string[]): <T>(values: T[]) => {[index:string]: T};
zipObj<T>(keys: string[], values: T[]): {[index: string]: T};
zipObj(keys: string[]): <T>(values: T[]) => {[index: string]: T};


/**
Expand Down