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

fix: FunctionKey and NonFunctionKeys #95

Merged
merged 4 commits into from
Jul 18, 2019
Merged

fix: FunctionKey and NonFunctionKeys #95

merged 4 commits into from
Jul 18, 2019

Conversation

promer94
Copy link
Contributor

#41 Description
FunctionKeys and NonFunctionKeys cant work with optional keys
example

type FunctionKeys<T extends object> = {
  [K in keyof T]: T[K] extends Function ? K : never
}[keyof T]

export type NonFunctionKeys<T extends object> = {
  [K in keyof T]: T[K] extends Function ? never : K
}[keyof T];

type MixedProps = {
  name: string;
  setName: (name: string) => void;
  someKeys?: string;
  someFn?: (...args: any) => any;
};
// "setName" | undefined
type Keys = FunctionKeys<MixedProps>
// "name" | "someKeys" | "someFn" | undefined
type newKey = NonFunctionKeys<MixedProps>

Checklist

  • I have read CONTRIBUTING.md
  • I have linked all related issues above
  • I have rebased my branch

For bugfixes:

  • I have added at least one unit test to confirm the bug have been fixed
  • I have checked and updated TOC and API Docs when necessary

Copy link
Owner

@piotrwitek piotrwitek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @promer94, thanks for the PR. The current behavior is intentional.

To get non-nullable keys you could use type composition like this:

type OmitOptional<T> = Omit<T, OptionalKeys<T>>;
type Keys = FunctionKeys<OmitOptional<MixedProps>>

I like that you extended tests, and I would gladly merge them but without optional keys change highlighted in the comments.

*
* // Expect: "setName"
* type Keys = FunctionKeys<MixedProps>;
*/
export type FunctionKeys<T extends object> = {
[K in keyof T]: T[K] extends Function ? K : never
[K in keyof T]-?: T[K] extends Function ? K : never
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this change, it's not desired.

}[keyof T];

/**
* NonFunctionKeys
* @desc get union type of keys that are non-functions in object type `T`
* @example
* type MixedProps = { name: string; setName: (name: string) => void };
* type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
*
* // Expect: "name"
Copy link
Owner

@piotrwitek piotrwitek Jul 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • // Expect: "name" | "someKeys"

@@ -89,26 +89,30 @@ export type NonUndefined<A> = A extends undefined ? never : A;
* FunctionKeys
* @desc get union type of keys that are functions in object type `T`
* @example
* type MixedProps = { name: string; setName: (name: string) => void };
* type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
*
* // Expect: "setName"
Copy link
Owner

@piotrwitek piotrwitek Jul 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Expect: "setName" | "someFn"

@promer94
Copy link
Contributor Author

Thanks for your feedback 😀.
But i'm confused now.

type FunctionKeys<T extends object> = {
  [K in keyof T]: T[K] extends Function ? K : never
}[keyof T]

type MixedProps = {
  name: string;
  setName: (name: string) => void;
  someKeys?: string;
  someFn?: (...args: any) => any;
};
// Expect: "setName" | undefined  
type Keys = FunctionKeys<MixedProps>

if i don't change the implementation, the type of Keys would be 'setName' | undefined rather than 'setName' | 'someFn'.

I'm new to Typescript, let me know if i am wrong

@piotrwitek
Copy link
Owner

@promer94 Ok I see now, it seems the type is broken, it definitely shouldn't include undefined.
Could you please try to exclude only undefined value but still preserving optional keys?

This should work

export type FunctionKeys<T extends object> = {
  [K in keyof T]-?: NonUndefined<T[K]> extends Function ? K : never
}[keyof T];

Copy link
Owner

@piotrwitek piotrwitek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks sweet! Great job @promer94, thanks.

@piotrwitek piotrwitek merged commit ad32857 into piotrwitek:master Jul 18, 2019
@promer94 promer94 deleted the fixKeys branch July 27, 2019 14:41
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

Successfully merging this pull request may close these issues.

2 participants