Skip to content

Commit

Permalink
Fix Except not working with generic properties (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
szmarczak committed Sep 10, 2021
1 parent 70fe524 commit ad02560
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 11 deletions.
35 changes: 34 additions & 1 deletion source/except.d.ts
@@ -1,3 +1,34 @@
import {IsEqual} from './internal';

/**
Filter out keys from an object.
Returns `never` if `Exclude` is strictly equal to `Key`.
Returns `never` if `Key` extends `Exclude`.
Returns `Key` otherwise.
@example
```
type Filtered = Filter<'foo', 'foo'>;
//=> never
```
@example
```
type Filtered = Filter<'bar', string>;
//=> never
```
@example
```
type Filtered = Filter<'bar', 'foo'>;
//=> 'bar'
```
@see {Except}
*/
type Filter<KeyType, ExcludeType> = IsEqual<KeyType, ExcludeType> extends true ? never : (KeyType extends ExcludeType ? never : KeyType);

/**
Create a type from an object type without certain keys.
Expand All @@ -21,4 +52,6 @@ type FooWithoutA = Except<Foo, 'a' | 'c'>;
@category Utilities
*/
export type Except<ObjectType, KeysType extends keyof ObjectType> = Pick<ObjectType, Exclude<keyof ObjectType, KeysType>>;
export type Except<ObjectType, KeysType> = {
[KeyType in keyof ObjectType as Filter<KeyType, KeysType>]: ObjectType[KeyType];
};
11 changes: 1 addition & 10 deletions source/includes.d.ts
@@ -1,13 +1,4 @@
/**
Returns a boolean for whether the two given types are equal.
@link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
*/
type IsEqual<T, U> =
(<G>() => G extends T ? 1 : 2) extends
(<G>() => G extends U ? 1 : 2)
? true
: false;
import {IsEqual} from './internal';

/**
Returns a boolean for whether the given array includes the given item.
Expand Down
11 changes: 11 additions & 0 deletions source/internal.d.ts
@@ -0,0 +1,11 @@
/**
Returns a boolean for whether the two given types are equal.
@link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
@link https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript/68963796#68963796
*/
export type IsEqual<T, U> =
(<G>() => G extends T ? 1 : 2) extends
(<G>() => G extends U ? 1 : 2)
? true
: false;
11 changes: 11 additions & 0 deletions test-d/except.ts
Expand Up @@ -3,3 +3,14 @@ import {Except} from '../index';

declare const except: Except<{a: number; b: string}, 'b'>;
expectType<{a: number}>(except);

// Generic properties
interface Example {
[key: string]: unknown;
foo: number;
bar: string;
}

const test: Except<Example, 'bar'> = {foo: 123, bar: 'asdf'};
expectType<number>(test.foo);
expectType<unknown>(test.bar);

0 comments on commit ad02560

Please sign in to comment.