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

Ramda Omit should return Partial<T> instead of T #183

Open
nonsensecreativity opened this issue Jul 7, 2017 · 8 comments
Open

Ramda Omit should return Partial<T> instead of T #183

nonsensecreativity opened this issue Jul 7, 2017 · 8 comments
Assignees

Comments

@nonsensecreativity
Copy link

nonsensecreativity commented Jul 7, 2017

There are few type issue on Ramda declaration

for example:

omit<T>(names: List<Prop>, obj: T): T;
omit(names: List<Prop>): <T>(obj: T) => T;

should be

omit<T>(names: List<Prop>, obj: T): Partial<T>;
omit(names: List<Prop>): <T>(obj: T) => Partial<T>;

or maybe a Pict<T1, T2>

omitting means removing parts of object specified in the second argument and return new object without the specified lists of key, so it should return Partial instead of T since it will returning only some part of the object key value

@KiaraGrouwstra
Copy link
Member

Yeah, fair enough. That said, at this point I did figure out how to do type level omit now. Put it in a gist but currently on phone.

@KiaraGrouwstra
Copy link
Member

For reference, my progress on typing it further (see here):

export type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;

// needs TS 2.5
export type Diff<T extends string, U extends string> =
({[P in T]: P } &
{ [P in U]: never } &
{ [k: string]: never })[T];

// alternative for older TS:

export type UnionDiff_<Big extends string, Small extends string> =
{[K in Big]: { 1: Union2Keys<Big>[K], 0: never }[Not<UnionHasKey<Small, K>>]}//[Big];

export type UnionDiff<
Big extends string,
Small extends string,
Step extends UnionDiff_<Big, Small> = UnionDiff_<Big, Small>
> = Step[Big];

I'd like to retype the whole library more accurately with things like this, but still got a few obstacles and need to test a lot more whether things wouldn't break down with less granular types.

Until then, feel free to send a PR to make it use Partial!

@nonsensecreativity
Copy link
Author

nonsensecreativity commented Jul 8, 2017

Currently my hack is

omit<O>(lists: string[], obj: Dict<any>): O with this I will also get the auto complete for outputted object keys

the T generic is used for the OUTPUT I was looking for.

When using Partials<T> or Pick<T, U>, the keys of object inputted still remain in the results omitted.

Also in Partial<T> every key is assigned an undefined on the results, this is not really helpful since I need to keep checking the key with if not undefined even though the value is defined.

I also tried with this one

omit<I, O>( lists: [keyof I], obj: I): O

interface Input {
  a: string;
  b: string;
}

interface Output {
  a: string;
}

omit<Input, Output>( ['b'], { a: 'a', b: 'b' } ) // got tooltips when inputting array of keys, got autocomplete for object keys in results and I can keep the object values type in VSCODE

By specifing type of Input and Output object, since I use VSCODE it helps me with tips on which key I can input on and which key value pairs I get back from the result. I only use this one if I have a huge lists of object keys in my third party library and want to avoid typo.

I think currently it's impossible to get difference between object in typescript. I have checked every default definitions library from typescript and core-js itself. There is no single implementation of difference between two stuffs.

@KiaraGrouwstra
Copy link
Member

omit<O>(lists: string[], obj: Dict<any>): O

We used to have typings like this, but I think they don't add much value: it seems little different from just explicitly casting the result like <T> omit(k, o). How would you see that?

I think currently it's impossible to get difference between object in typescript.

Did you check my link? You're not likely to find it used anywhere yet cuz we just only recently figured out how one might be able to do it.
You're right though, typings currently out there don't really go this far yet, standard library included.

@nonsensecreativity
Copy link
Author

Yes, I checked your link, I also try all of the type definition in your gist link but nothing works

@KiaraGrouwstra
Copy link
Member

I can't get it to work as a function yet either, just like R.path (see mention of #12290 here):

const keys: ['a', 'b'] = ['a', 'b'];
const obj: { a: 1, b: 2, c: 3 } = { a: 1, b: 2, c: 3 };
declare function omit<T, Keys extends string[]>(names: Keys, obj: T): Omit<T, TupleToUnion<Keys>>;
const omitTest = omit(keys, obj);
// expect {c:3}, get Pick<{ a: 1; b: 2; c: 3; }, "a" | "b" | "c">
declare function omit2<Keys extends string[]>(names: Keys): TupleToUnion<Keys>;
const omitTest2 = omit2(keys);
// expect 'a'|'b', got never
type abc1 = TupleToUnion<['a', 'b']>;
// 'a'|'b'
type abc2 = TupleToUnion<string[]>;
// gives never, did omitTest2 have it turn into string[] too?
declare function omit3<Keys extends string[]>(names: Keys): Keys;
const omitTest3 = omit3(keys);
// ["a", "b"] as expected, no info lost here... weird.

So yeah, the jump to functions is one thing I'm still having trouble with...

@KiaraGrouwstra
Copy link
Member

Filed as bug here now.

KiaraGrouwstra referenced this issue in ikatyang/types-ramda Jul 20, 2017
@KiaraGrouwstra KiaraGrouwstra self-assigned this Aug 19, 2017
@KiaraGrouwstra
Copy link
Member

Actually works now on master. Guess there is hope!
I'd better further test type-level programming in typical before we really dive into it over here though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants