TypeScriptの条件付き型


65

TypeScriptで条件付き型を使用できるかどうか疑問に思っていましたか?

現在、私は次のインターフェースを持っています:

interface ValidationResult {
  isValid: boolean;
  errorText?: string;
}

しかし、私は削除したいerrorText、と場合にのみ、それを持ってisValidいるfalseように必要なプロパティ。

私はそれを次のインターフェースとして書くことができればいいのに:

interface ValidationResult {
  isValid: true;
}

interface ValidationResult {
  isValid: false;
  errorText: string;
}

しかし、ご存知のとおり、それは不可能です。それで、この状況についてあなたの考えは何ですか?


、ときに意味するかisValidですかfalse
特定のパフォーマンス

18
isValidは冗長です。errorTextがあるだけの場合もあり、errorTextがnullの場合、エラーは発生しません。
MTilsted

はい、@ MTilsted、あなたは正しいですが、レガシーコードのために私たちはそれを維持する必要があります。
アルマン

回答:


89

この種のロジックをモデル化する1つの方法は、次のような共用体タイプを使用することです

interface Valid {
  isValid: true
}

interface Invalid {
  isValid: false
  errorText: string
}

type ValidationResult = Valid | Invalid

const validate = (n: number): ValidationResult => {
  return n === 4 ? { isValid: true } : { isValid: false, errorText: "num is not 4" }
}

コンパイラは、ブールフラグに基づいて型を絞り込むことができます

const getErrorTextIfPresent = (r: ValidationResult): string | null => {
  return r.isValid ? null : r.errorText
}

7
いい答えだ。そして、コンパイラが実際にここrで型Invalidである必要があることを伝えることができるのは魅力的です。
sleske

1
これを差別的組合といいます。かなりクールなもの:typescriptlang.org/docs/handbook/...
UmurKontacı

41

3番目のインターフェースの作成にのみ使用される複数のインターフェースの作成を回避するために、type代わりに次のように直接代替することもできます。

type ValidationResult = {
    isValid: false;
    errorText: string;
} | {
    isValid: true;
};

20

バグによって実証組合は私がこれを扱うお勧めする方法です。それにもかかわらず、Typescriptに条件付きタイプ」と呼ばれるものがあり、これを処理できます。

type ValidationResult<IsValid extends boolean = boolean> = (IsValid extends true
    ? { isValid: IsValid; }
    : { isValid: IsValid; errorText: string; }
);


declare const validation: ValidationResult;
if (!validation.isValid) {
    validation.errorText;
}

これValidationResult(実際ValidationResult<boolean>にはデフォルトのパラメータが原因です)は、バグの回答または特定のパフォーマンスの回答で生成された共用体と同等であり、同じ方法で使用できます。

ここでの利点は、あなたも知ら周り渡すことができることであるValidationResult<false>値を、その後、あなたがテストを持っていないでしょうisValid、あることを知られているようにfalseしてerrorString存在することが知られているであろう。おそらく、このような場合には必要ありません。条件付きの型は複雑でデバッグが困難な場合があるため、不必要に使用しないでください。しかし、あなたはそうすることができ、それは言及する価値があるように思われました。


3
これらは時々本当に役立つと確信しています。しかし、私には、構文は本当に厄介に見えます。
Peilonrayz

3
@Peilonrayzええと、他のTypescriptコーディングとの整合性がよくextends、適切な演算子です。また、特にそれを使用してタイプを掘り下げることもできるため、非常に強力ですtype SecondOf<T> = T extends Pair<any, infer U> ? U : never;
KRyan

@KRyan私はそれについて考えてきました。それは基本的にSecondOf<number>「に拡張する」という意味Pair<any, number>ですか?「本を表紙で判断してはいけない」という言葉がここでは適切だと思います。
Peilonrayz

@Peilonrayzああ、いいえ。むしろ反対です。SecondOf<Pair<any, number>>はに評価されnumberます。は拡張されないのでfalse であるため、とSecondOf<number>評価されますnevernumber extends Pair<any, infer U>numberPair
KRyan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.