相互排他タイプ
10781 ワード
間の違い
まず始めましょう.
セット セット またはセット しかし、これはどんな形でも強制されません.ハードコードされた値を書きましょう.
ユニオンタイプ
type
とinterface
タイプスクリプトのsは、彼らが非常に類似しているので、必ずしも明らかでありません.しかし、微妙な違いがあります.この記事では、型だけで実現できる機能について説明します.まず始めましょう.
type Resource<Type = any> = {
progress: 'pending' | 'success' | 'error'
error?: Error
data?: Type
}
このような構造は以下のように使われる:progress
to "pending"
リソースへのアクセスprogress
to "success"
とdata
成功の場合progress
to "error"
とエラーerror
失敗した場合// this one is a possible expected value :
const res: Resource = {
progress: 'pending'
}
// but this one is unexpected, however I can write it !
const res: Resource = {
progress: 'pending',
data: 42 // 😵 oh no ! this is allowed
}
// this one doesn't make sense either !
const res: Resource = {
progress: 'pending',
data: 42, // 😵
error: new Error() // 😵
}
ユニオンタイプ
タイプスクリプトの型の1つの強さは、型を結合する可能性を持つことです.つの相互排他タイプの結合として型を書き直しましょう.
type Resource<Type = any> = {
progress: 'pending'
} | {
progress: 'success'
data: Type
} | {
progress: 'error'
error: Error
}
そして、それはうまくいきます!さあ書きましょう
// I can't write it anymore ! There is an error !
const res: Resource = {
progress: 'pending',
data: 42 // 👈 yes ! there is an error
}
// the fix :
const res: Resource = {
progress: 'success', // 👌
data: 42
}
今までのところ、これまでに、タイプスクリプトは現在、予想される方法の誤りを防ぎます.また、次のコードを書くのを防ぎますdata
のフィールドではないres
:
const res: Resource = getSomeResource();
doSomething(res.data); // 👈 error !
データにアクセスするには、型ガードを使用して、別の種類のコードで実際の型を再構築することができます.
const res: Resource = getSomeResource();
if (res.progress === 'success') {
doSomething(res.data); // 👌
}
タイプガードは確かにタイプスクリプトの中で最も貴重な機能の一つですが、残念ながら、これも書きません.
const res: Resource = getSomeResource();
const data = res.data ?? 42; // 😖 oh no ! error !
なぜ?もう一度言いましょうdata
のフィールドではないres
!
相互排他型権利
それで、我々のタイプを固定しましょうdata
任意の場合に定義されるフィールド
type Resource<Type = any> = {
progress: 'pending'
data?: never
error?: never
} | {
progress: 'success'
data: Type
error?: never
} | {
progress: 'error'
data?: never
error: Error
}
そのようにdata
フィールドは結果のunion型の無条件部分です変更は時々設定できません.
// I still can't write that !
const res: Resource = {
progress: 'pending',
data: 42 // 👈 yes ! there is an error !
}
...しかし、我々がアクセスすることができるすべての回:
// but now, I can write that :
const res: Resource = getSomeResource();
const data = res.data ?? 42; // 👌 got it !
...そしてもちろんタイプガードはまだ期待された方法で働いています!
その結果、最後のタイプ定義は少し冗長です、しかし、コードはより少なくなります!したがって、特定の状況でのみこのテクニックを適用する価値があります.
読んでくださってありがとうございます.
Reference
この問題について(相互排他タイプ), 我々は、より多くの情報をここで見つけました
https://dev.to/ppoulard/mutually-exclusive-types-done-right-23je
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
type Resource<Type = any> = {
progress: 'pending'
} | {
progress: 'success'
data: Type
} | {
progress: 'error'
error: Error
}
// I can't write it anymore ! There is an error !
const res: Resource = {
progress: 'pending',
data: 42 // 👈 yes ! there is an error
}
// the fix :
const res: Resource = {
progress: 'success', // 👌
data: 42
}
const res: Resource = getSomeResource();
doSomething(res.data); // 👈 error !
const res: Resource = getSomeResource();
if (res.progress === 'success') {
doSomething(res.data); // 👌
}
const res: Resource = getSomeResource();
const data = res.data ?? 42; // 😖 oh no ! error !
それで、我々のタイプを固定しましょう
data
任意の場合に定義されるフィールドtype Resource<Type = any> = {
progress: 'pending'
data?: never
error?: never
} | {
progress: 'success'
data: Type
error?: never
} | {
progress: 'error'
data?: never
error: Error
}
そのようにdata
フィールドは結果のunion型の無条件部分です変更は時々設定できません.// I still can't write that !
const res: Resource = {
progress: 'pending',
data: 42 // 👈 yes ! there is an error !
}
...しかし、我々がアクセスすることができるすべての回:// but now, I can write that :
const res: Resource = getSomeResource();
const data = res.data ?? 42; // 👌 got it !
...そしてもちろんタイプガードはまだ期待された方法で働いています!その結果、最後のタイプ定義は少し冗長です、しかし、コードはより少なくなります!したがって、特定の状況でのみこのテクニックを適用する価値があります.
読んでくださってありがとうございます.
Reference
この問題について(相互排他タイプ), 我々は、より多くの情報をここで見つけました https://dev.to/ppoulard/mutually-exclusive-types-done-right-23jeテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol