Reputation: 21380
I'd like to exclude a single property from the type. How can I do that?
For example I have
interface XYZ {
x: number;
y: number;
z: number;
}
And I want to exclude property z
to get
type XY = { x: number, y: number };
Upvotes: 512
Views: 546593
Reputation: 74480
Omit ...
type T1 = Omit<XYZ, "z"> // { x: number; y: number; }
type T2 = Omit<XYZ, "y" | "z"> // { x: number; }
e.g. all string types:
type Keys_StringExcluded<T> =
{ [K in keyof T]: T[K] extends string ? never : K }[keyof T]
type XYZ = { x: number; y: string; z: number; }
type T3a = Pick<XYZ, Keys_StringExcluded<XYZ>> // { x: number; z: number; }
Shorter version with TS 4.1 key remapping / as
clause in mapped types (PR):
type T3b = { [K in keyof XYZ as XYZ[K] extends string ? never : K]: XYZ[K] }
// { x: number; z: number; }
string
patterne.g. exclude getters (props with 'get' string prefixes)
type OmitGet<T> = {[K in keyof T as K extends `get${infer _}` ? never : K]: T[K]}
type XYZ2 = { getA: number; b: string; getC: boolean; }
type T4 = OmitGet<XYZ2> // { b: string; }
Note: Above template literal types are supported with TS 4.1. You can also write get${string}
instead of get${infer _}
here.
Pick
, Omit
and other utility types
How to Pick and rename certain keys using Typescript? (rename instead of exclude)
Upvotes: 205
Reputation: 32146
In TypeScript 3.5, the Omit
type was added to the standard library. See examples below for how to use it.
In TypeScript 2.8, the Exclude
type was added to the standard library, which allows an omission type to be written simply as:
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
You cannot use the Exclude
type in versions below 2.8, but you can create a replacement for it in order to use the same sort of definition as above. However, this replacement will only work for string types, so it is not as powerful as Exclude
.
// Functionally the same as Exclude, but for strings only.
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T]
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>
And an example of that type in use:
interface Test {
a: string;
b: number;
c: boolean;
}
// Omit a single property:
type OmitA = Omit<Test, "a">; // Equivalent to: {b: number, c: boolean}
// Or, to omit multiple properties:
type OmitAB = Omit<Test, "a"|"b">; // Equivalent to: {c: boolean}
Upvotes: 852
Reputation: 159
I do like that:
interface XYZ {
x: number;
y: number;
z: number;
}
const a:XYZ = {x:1, y:2, z:3};
const { x, y, ...last } = a;
const { z, ...firstTwo} = a;
console.log(firstTwo, last);
Upvotes: 3
Reputation: 17825
In Typescript 3.5+:
interface TypographyProps {
variant: string
fontSize: number
}
type TypographyPropsMinusVariant = Omit<TypographyProps, "variant">
Upvotes: 15
Reputation: 705
As of Typescript 3.5, the Omit helper will be included: TypeScript 3.5 RC - The Omit Helper Type
You can use it directly, and you should remove your own definition of the Omit helper when updating.
Upvotes: 5
Reputation: 5588
If you prefer to use a library, use ts-essentials.
import { Omit } from "ts-essentials";
type ComplexObject = {
simple: number;
nested: {
a: string;
array: [{ bar: number }];
};
};
type SimplifiedComplexObject = Omit<ComplexObject, "nested">;
// Result:
// {
// simple: number
// }
// if you want to Omit multiple properties just use union type:
type SimplifiedComplexObject = Omit<ComplexObject, "nested" | "simple">;
// Result:
// { } (empty type)
PS: You will find lots of other useful stuff there ;)
Upvotes: 9
Reputation: 8127
With typescript 2.8, you can use the new built-in Exclude
type. The 2.8 release notes actually mention this in the section "Predefined conditional types":
Note: The Exclude type is a proper implementation of the Diff type suggested here. [...] We did not include the Omit type because it is trivially written as
Pick<T, Exclude<keyof T, K>>
.
Applying this to your example, type XY could be defined as:
type XY = Pick<XYZ, Exclude<keyof XYZ, "z">>
Upvotes: 55
Reputation: 21380
I've found solution with declaring some variables and using spread operator to infer type:
interface XYZ {
x: number;
y: number;
z: number;
}
declare var { z, ...xy }: XYZ;
type XY = typeof xy; // { x: number; y: number; }
It works, but I would be glad to see a better solution.
Upvotes: 31