1 | import { type IsEqual } from "./IsEqual.js";
|
2 | /**
|
3 | Filter out keys from an object.
|
4 |
|
5 | Returns `never` if `Exclude` is strictly equal to `Key`.
|
6 | Returns `never` if `Key` extends `Exclude`.
|
7 | Returns `Key` otherwise.
|
8 |
|
9 | @example
|
10 | ```
|
11 | type Filtered = Filter<'foo', 'foo'>;
|
12 | //=> never
|
13 | ```
|
14 |
|
15 | @example
|
16 | ```
|
17 | type Filtered = Filter<'bar', string>;
|
18 | //=> never
|
19 | ```
|
20 |
|
21 | @example
|
22 | ```
|
23 | type Filtered = Filter<'bar', 'foo'>;
|
24 | //=> 'bar'
|
25 | ```
|
26 | */
|
27 | type Filter<KeyType, ExcludeType> = IsEqual<KeyType, ExcludeType> extends true ? never : KeyType extends ExcludeType ? never : KeyType;
|
28 | interface ExceptOptions {
|
29 | /**
|
30 | Disallow assigning non-specified properties.
|
31 |
|
32 | Note that any omitted properties in the resulting type will be present in autocomplete as `undefined`.
|
33 |
|
34 | @defaultValue false
|
35 | */
|
36 | requireExactProps?: boolean;
|
37 | }
|
38 | /**
|
39 | Create a type from an object type without certain keys.
|
40 |
|
41 | We recommend setting the `requireExactProps` option to `true`.
|
42 |
|
43 | This type is a stricter version of [`Omit`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html#the-omit-helper-type). The `Omit` type does not restrict the omitted keys to be keys present on the given type, while `Except` does. The benefits of a stricter type are avoiding typos and allowing the compiler to pick up on rename refactors automatically.
|
44 |
|
45 | This type was proposed to the TypeScript team, which declined it, saying they prefer that libraries implement stricter versions of the built-in types ([microsoft/TypeScript#30825](https://github.com/microsoft/TypeScript/issues/30825#issuecomment-523668235)).
|
46 |
|
47 | @example
|
48 | ```
|
49 | import {Except} from 'type-fest';
|
50 |
|
51 | type Foo = {
|
52 | a: number;
|
53 | b: string;
|
54 | };
|
55 |
|
56 | type FooWithoutA = Except<Foo, 'a'>;
|
57 | //=> {b: string}
|
58 |
|
59 | const fooWithoutA: FooWithoutA = {a: 1, b: '2'};
|
60 | //=> errors: 'a' does not exist in type '{ b: string; }'
|
61 |
|
62 | type FooWithoutB = Except<Foo, 'b', {requireExactProps: true}>;
|
63 | //=> {a: number} & Partial<Record<"b", never>>
|
64 |
|
65 | const fooWithoutB: FooWithoutB = {a: 1, b: '2'};
|
66 | //=> errors at 'b': Type 'string' is not assignable to type 'undefined'.
|
67 | ```
|
68 | */
|
69 | export type Except<ObjectType, KeysType extends keyof ObjectType, Options extends ExceptOptions = {
|
70 | requireExactProps: false;
|
71 | }> = {
|
72 | [KeyType in keyof ObjectType as Filter<KeyType, KeysType>]: ObjectType[KeyType];
|
73 | } & (Options["requireExactProps"] extends true ? Partial<Record<KeysType, never>> : {});
|
74 | export {};
|