2
Reduxの場合(特にこの問題はReduxとは関係ありません)リデューサーが使用するアクションの名前が必要ですが、名前とアクション減速機で使用される。だから私はこのコードを書いた:私は例をしようとすると、文字列型パラメータが強制されていない
interface TypedAction<N> {
type: N;
}
type TypedReducer<S, A extends TypedAction<any>> = (state: S, action: A) => S;
function addReducer<S, R extends TypedReducer<S, A>, A extends TypedAction<N>, N>(initialState: S, actionName: N, reducer: R): {} {
// doesn't really matter what is returned here
// the point is I need the actionName during run time
// but want it to correspond with the reducer's action's name at compile time
return {
[actionName.toString()]: reducer
};
}
は、しかし:
interface MyAction extends TypedAction<'MyAction'> {
foo: string;
}
const myActionReducer: TypedReducer<number, MyAction> = (state: number, action: MyAction) => state+1;
addReducer(1, "foo", myActionReducer); // should give a compile error, because "foo" and is not of type "MyAction"
はなぜ活字体は"foo"
は"MyAction"
であることを強制しませんか?
すべての 'addReducer'引数をまとめて考えると、' foo "というユニオン型として推論されたNを持つすべての制約を満たすことができます。 "MyAction"。なぜTypeScriptは '' foo ''から' 'foo' 'の型を広げるのですか? "MyAction"?おそらく、他の現実のコードをコンパイルして、何人かの人がエラーなしでコンパイルしなければならないと考えたからでしょう。 'N'が(単数の)文字列型でなければならないという制約を加える方法はありますか?私は知らない。 – artem
私の同僚は実際にそれを理解しました。彼は答えを掲示するでしょう。 'TypedAction'と' addReducer' TypeScriptのNの定義の後ろに 'extends string'を置くと、突然期待どおりに動作します。私はなぜか分からない。 –