UNPKG

2.38 kBTypeScriptView Raw
1import type {IsEqual} from './is-equal';
2
3/**
4Filter out keys from an object.
5
6Returns `never` if `Exclude` is strictly equal to `Key`.
7Returns `never` if `Key` extends `Exclude`.
8Returns `Key` otherwise.
9
10@example
11```
12type Filtered = Filter<'foo', 'foo'>;
13//=> never
14```
15
16@example
17```
18type Filtered = Filter<'bar', string>;
19//=> never
20```
21
22@example
23```
24type Filtered = Filter<'bar', 'foo'>;
25//=> 'bar'
26```
27
28@see {Except}
29*/
30type Filter<KeyType, ExcludeType> = IsEqual<KeyType, ExcludeType> extends true ? never : (KeyType extends ExcludeType ? never : KeyType);
31
32type ExceptOptions = {
33 /**
34 Disallow assigning non-specified properties.
35
36 Note that any omitted properties in the resulting type will be present in autocomplete as `undefined`.
37
38 @default false
39 */
40 requireExactProps?: boolean;
41};
42
43/**
44Create a type from an object type without certain keys.
45
46We recommend setting the `requireExactProps` option to `true`.
47
48This 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.
49
50This 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)).
51
52@example
53```
54import type {Except} from 'type-fest';
55
56type Foo = {
57 a: number;
58 b: string;
59};
60
61type FooWithoutA = Except<Foo, 'a'>;
62//=> {b: string}
63
64const fooWithoutA: FooWithoutA = {a: 1, b: '2'};
65//=> errors: 'a' does not exist in type '{ b: string; }'
66
67type FooWithoutB = Except<Foo, 'b', {requireExactProps: true}>;
68//=> {a: number} & Partial<Record<"b", never>>
69
70const fooWithoutB: FooWithoutB = {a: 1, b: '2'};
71//=> errors at 'b': Type 'string' is not assignable to type 'undefined'.
72```
73
74@category Object
75*/
76export type Except<ObjectType, KeysType extends keyof ObjectType, Options extends ExceptOptions = {requireExactProps: false}> = {
77 [KeyType in keyof ObjectType as Filter<KeyType, KeysType>]: ObjectType[KeyType];
78} & (Options['requireExactProps'] extends true
79 ? Partial<Record<KeysType, never>>
80 : {});