UNPKG

2.4 kBTypeScriptView Raw
1import { type IsEqual } from "./IsEqual.js";
2/**
3Filter out keys from an object.
4
5Returns `never` if `Exclude` is strictly equal to `Key`.
6Returns `never` if `Key` extends `Exclude`.
7Returns `Key` otherwise.
8
9@example
10```
11type Filtered = Filter<'foo', 'foo'>;
12//=> never
13```
14
15@example
16```
17type Filtered = Filter<'bar', string>;
18//=> never
19```
20
21@example
22```
23type Filtered = Filter<'bar', 'foo'>;
24//=> 'bar'
25```
26*/
27type Filter<KeyType, ExcludeType> = IsEqual<KeyType, ExcludeType> extends true ? never : KeyType extends ExcludeType ? never : KeyType;
28interface 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/**
39Create a type from an object type without certain keys.
40
41We recommend setting the `requireExactProps` option to `true`.
42
43This 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
45This 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```
49import {Except} from 'type-fest';
50
51type Foo = {
52 a: number;
53 b: string;
54};
55
56type FooWithoutA = Except<Foo, 'a'>;
57//=> {b: string}
58
59const fooWithoutA: FooWithoutA = {a: 1, b: '2'};
60//=> errors: 'a' does not exist in type '{ b: string; }'
61
62type FooWithoutB = Except<Foo, 'b', {requireExactProps: true}>;
63//=> {a: number} & Partial<Record<"b", never>>
64
65const fooWithoutB: FooWithoutB = {a: 1, b: '2'};
66//=> errors at 'b': Type 'string' is not assignable to type 'undefined'.
67```
68*/
69export 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>> : {});
74export {};