ジェネリックと条件が型定義で使用されている場合、Typescriptがswitchステートメントの型を推測しない

ジェイク

関数の型定義があります。次のように、2番目の引数の型を最初の引数の型を条件として定義しています。

const FOO = "FOO";
const BAR = "BAR";

let fooPayload = {
    zip: "zap"
}
let barPayload = {
    cat: "dog"
}

type ActionTypes = typeof FOO | typeof BAR;
interface MyFunction<T extends ActionTypes = ActionTypes> {
  (
    action: {
      type: T;
      payload: T extends typeof FOO
        ? typeof fooPayload
        : typeof barPayload;
    }
  ): boolean;
}

MyFunctionインターフェイスが参照する関数には、に基づいて切り替えaction.type、場合によってはaction.payload。を使用して何かを行うswitchステートメントが含まれています次に例を示します。

const myFunction:MyFunction = (action) => {
    switch (action.type) {
        case FOO:
            action.payload.zip = "new zap"
            return true
        case BAR: 
            action.payload.cat = "new dog"
            return false
        default:
            return false
    }
}

私が抱えている問題は、Typescriptがaction.payloadswitchステートメントから何をすべき正しく推測していないことです。たとえば、action.typeが「FOO」に等しい場合、それはでaction.payloadなければならないことを推測する必要がありますtypeof fooPayload代わりに、それはであると推測しtypeof fooPayload | typeof barPayloadます。

の型定義action.payloadはの値に基づいているため、これは意味がありませんaction.type。また、action.payload.zip「FOO」action.type等しい場合にのみ発生する可能性があるswitchステートメント内で呼び出されるため、の唯一の可能な型はであるaction.payload推測する必要がありtypeof fooPayloadます。

これがコード例です

私はここで何が間違っているのですか?

スペンサーパーク

これが問題を引き起こしている正確な場所はわかりませんが、一般的に問題は、typescriptがすでにうまく機能している狭い型の共用体を再発明しようとしていることです。

条件文は非常に興味深い機能ですが、分配法則であるため、定義された場所の範囲から外れるため、予期しない動作をすることがあります。

私はこれを別の方法で実装します:

interface Action<T, P> {
    type: T,
    payload: P
}

type Actions 
    = Action<typeof FOO, typeof FooPayload> 
    | Action<typeof BAR, typeof BarPayload> 
    ;

interface MyFunction {
  (action: Actions): boolean;
}

条件は必要ありません。typescriptを使用すると、スイッチで期待どおりにユニオンが絞り込まれます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ