「TはUを推測する」の限界を理解しようとしています


8

私は次のようなことを理解しました:

type GenericExample<T> = T extends (infer U) ? U : 'bar';

等しい:

type GenericExample<T> = T extends T ? T : 'bar';

しかし、物事がより複雑になると、TypeScriptは不平を言います。

type Types = 'text' | 'date' | 'articles' | 'params';

type MyExperiment<Type extends Types> =  { t : Type };

type MyExperimentsUnion = Types extends (infer U) ? MyExperiment<U> : never;
// Type 'U' does not satisfy the constraint 'Types'.
// Type 'U' is not assignable to type '"params"'.

組合に対するこの特定のケースの分布に推測されて、場所を取る必要があります。私は、これは間違っている理由をお願いしたいと思いますので、Uタイプがあるべきtext、その後、dateというように。それで、T extends (infer U)実際には何を意味し、いつそれを使用するのが適切でしょうか?

回答:


0

私はそれをあなたがそれを使用している方法で使用することを意図したものではないと思います-基本的にinfer、最も一般的にはジェネリックからタイプを「推論」(またはおそらくより良いネーミングを解決する)するために使用する必要があります。

あなたがそれを使用している方法、あなたは「動的な」部分を持たないタイプを作成しています(基本的にそれはジェネリックではありません)、それはそれが常に同じであることを意味し、したがって常に同じであるものから推論することは意味がありません。コンパイル時に、それTypesが拡張のみTypes & '...anything else'であることがすでにわかっているため、また、MyExperimentsUnion型の他の部分を定義できないため、ほとんど役に立ちinferません。

使用例

interface Action<T> {
    payload: T
}

type ExtractGeneric<T> = T extends Action<infer X> ? X : never

function getPayload<T extends Action<any>>(action: T): ExtractGeneric<T> {
    return action.payload;
}

const myAction = { payload: 'Test' };
const myPayloadWithResolvedType = getPayload(myAction);

上記の例でmyPayloadWithResolvedTypestring、解決された型になります。を使用していない場合はinfer、おそらく次のように、その戻り値の型を2番目のパラメータとして渡す必要があります。

function getPayloadNonExtract<T extends Action<U>, U>(action: T): U {
    return action.payload;
}

こちらが遊び場へのリンクです。

乾杯。


1
こんにちは、回答ありがとうございます。inferキーワードの一般的な目的は知っていると言わざるを得ませんがT extends (infer U)、条件付きタイプで有効であることを発見したのでこの奇妙な質問をしました。そのことに驚いて調査を開始しました。
Andrea Simone Costa

1
あなたの質問は理解できたと思いますが、typescriptでどのように解決しUますか?何であるべきMyExperiment<U>ですか?私は、意味U「サブクラス」のでなければならないTypesが、typescriptですが、正確に何であるかを判断することはできませんUあなたは(それが一般的なタイプではありません)任意の型を渡していないことから、そしてそれがデフォルトで設定される必要があり、なぜ私は表示されませんTypes。これがエラーが発生する理由の1つだと思いますが、もっと説明的かもしれないと私は同意しますが、開発者がinferそのように使用することを意図していないことを開発者が知っておくべきだということを彼らは確信しているようです。
zhuber

0

それはおそらく2セント以上の価値はありませんが:

type Types = 'text' | 'date' | 'articles' | 'params';
type MyExperiment<Type extends Types> =  { t : Type };

type MyExperimentsGenericUnion<T extends Types> = T extends (infer U) ? MyExperiment<U> : never;
// same error

type MyExperimentsUnionConstraint = any extends MyExperiment<infer U> ? MyExperiment<U> : never;
// no error

なぜMyExperimentsUnionConstraint機能するがMyExperimentsUnion機能しないのか、いくつかの理由を考えることができますが、意味をなすようにそれらを表現するための詳細な言語知識がありません。

例で説明するには:

  • MyExperimentsUnion、からTypes extends UUとして推論される可能性がTypes | 'bla'あり、その後MyExperiment<Type | 'bla'>機能しません。
  • ではMyExperimentsUnionConstraintU動作するものとしてのみ推測できますMyExperiment
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.