タイプからプロパティを除外


156

タイプから単一のプロパティを除外したいのですが。どうやってやるの?

例えば私は持っています

interface XYZ {
  x: number;
  y: number;
  z: number;
}

そして、私はz取得するプロパティを除外したい

type XY = { x: number, y: number };

回答:


333

TypeScript 3.5以降のバージョンの場合

TypeScript 3.5では、Omitタイプが標準ライブラリに追加されました。使用方法については、以下の例を参照してください。

TypeScript 3.5より前のバージョンの場合

TypeScript 2.8では、Exclude型が標準ライブラリに追加され、省略型を次のように簡単に記述できます。

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

TypeScriptのバージョンが2.8未満の場合

Exclude2.8より前のバージョンではタイプを使用できませんが、上記と同じ種類の定義を使用するためにタイプの代替を作成できます。ただし、この置換は文字列型に対してのみ機能するため、ほど強力ではありません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>>

そして、そのタイプの使用例:

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}

すごい!あなたが宣言されているDiff<T, U>(とTUのようなキーの使用可能なタイプのような)Tのための値としてキー同じとタイプ:-keyed 3種類の交差点のサブセットT、タイプneverUとし、タイプneverすべてのキーのために。次に、それをインデクサーに渡して、正しい値の型を取得します。私は正しいですか?
Qwertiy 2018年

5
うん!しかし、これには欠点があります。たとえば、Omit<{a?: string, b?: boolean}, "b">結果は{a: string | undefined}になりますundefinedが、値としては受け入れられますが、のオプションの修飾子は失われaます。:(
CRice

それは悲しいです...宣言して広げてそのように面白いとオプションの修飾子が保持されます...それを維持する他の方法はありますか?
Qwertiy 2018年

1
@Qwertiyうまくいきました!どうもありがとう!投稿を編集しました。しかし、違いは何だったのPickかと思います。何があったのかは、私が見る限り、型定義と文字通り同じだったからです。
CRice

3
TS 3.5の場合、標準ライブラリのの定義は、Omitここで示したものとは異なります。stdlibでは、それはtype Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;わずかですが、多少の議論の原因となっています。その違いに注意してください。
CRice

41

typescript 2.8では、新しい組み込みExclude型を使用できます。2.8リリースノートには、実際の「定義済みの条件タイプ」でこれを言及します:

注:Excludeタイプは、ここで提案されているDiffタイプの適切な実装です。[...] Omitタイプは、簡単にと書かれてPick<T, Exclude<keyof T, K>>いるため、含めませんでした。

これを例に適用すると、タイプXYは次のように定義できます。

type XY = Pick<XYZ, Exclude<keyof XYZ, "z">>

19

いくつかの変数を宣言し、スプレッド演算子を使用して型を推測することで解決策を見つけました:

interface XYZ {
  x: number;
  y: number;
  z: number;
}

declare var { z, ...xy }: XYZ;

type XY = typeof xy; // { x: number; y: number; }

それは機能しますが、私はより良い解決策を見てうれしいです。


3
これは、2.8より前の優れたソリューションです。typeoftypescriptのあまり評価されていない機能の1つです。
Jason Hoetger

1
賢い、私はそれが好きです:)!(2.8より前の場合)
maxime1992

結果に文字列型のzを追加する方法
user602291

@ user602291 、type Smth = XY & { z: string };?
Qwertiy 2018

1
これはtypescriptの古いバージョンに最適です。私は2.3で動作するように適切な答えを得ることができませんでしたが、これはうまくいきました。
k0pernikus

6

ライブラリを使用する場合は、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:他にもたくさんの便利なものがあります;)



4

活字体3.5+

interface TypographyProps {
    variant: string
    fontSize: number
}

type TypographyPropsMinusVariant = Omit<TypographyProps, "variant">

0

私はそれが好きです:

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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.