TypeScriptバージョン: 2.2.2
ジェネリックスがどのように機能するかを誤解しているかもしれませんが(もしそうなら、正しい方向に向けてください)、これはバグのようです。
コード
// A *self-contained* demonstration of the problem follows...
interface BaseState {
on: boolean;
};
class Component {
state: BaseState;
setState(state: BaseState) {
this.state = state;
}
onInput({ value }: { value: number }) {
this.setState({ on: value > 0 }); // no error
}
}
class GenericComponent<State extends BaseState> {
state: State;
setState(state: State) {
this.state = state
}
onInput({ value }: { value: number }) {
this.setState({ on: value > 0 }); // error Argument of type '{ on: boolean; }' is not assignable to parameter of type 'State'.
}
}
予想される行動:
上記の例のComponent
クラスでは、 BaseState
インターフェイスを直接使用してもエラーは発生しません。 State
ジェネリックはBaseState
明示的に拡張するため、 GenericComponent
クラスからも同じ動作が期待されます。
実際の動作:
代わりに、 this.setState({ on: value > 0 });
関連する次のエラーが発生します:「タイプ '{on:boolean;}'の引数はタイプ 'State'のパラメーターに割り当てることができません。」
これを書くとどうなるか考えてみてください
var t = new GenericComponent<{on: boolean, thing: string}>();
t.onInput({ value: 30 });
t.state.thing.substr(0); // 'thing' property should exist, but doesn't
簡単な例を次に示します。
class Stateful<State extends { on: boolean }> {
state: State = {
on: true
}; // error
}
これが機能しない理由は、 Stateful
が{ on: boolean }
正確に同等の型引数でインスタンス化された場合にのみ有効になるためです。
基本的に、タイプT
が存在し、インスタンス化が有効であるようにStateful
のタイプ引数の制約を満たしますが、これは_すべての_タイプに当てはまりませんT
ここでT
は、 Stateful
の型引数の制約を満たします。
したがって、上記の誤ったコードは、すべてのタイプのT<T>
、 T,
ステートフルであると主張しています。
論理的には、次のように見ることができます。
アサーション
P
タイプ{ on: boolean }
T
がP
に割り当て可能であるようなすべてのタイプT
について、上記のStateful<T>
の定義は有効です。反例による反証
U
タイプ{ on: boolean, value: number }
U
は定義上P
->に割り当てることができますStateful<U>
は無効です->置換によるT
がP
割り当て可能で、 Stateful<T>
が無効なインスタンス化であるようなタイプT
が存在します->含意によって@RyanCavanaugh @aluanhaddadシュート、私はそれを知っていました。 問題をもっと単純なものに絞り込もうとしているときに、私は混乱しました。 もう一度試してみましょう。 この場合、パーシャルを使用するのはどうですか? それでも同様のエラーが発生します。
interface BaseState {
on: boolean;
};
class Component {
state: BaseState;
setState(partialState: Partial<BaseState>) {
this.state = { ...this.state, ...partialState };
}
onInput({ value }: { value: number }) {
this.setState({ on: value > 0 }); // no error
}
}
class GenericComponent<State extends BaseState> {
state: State;
setState(partialState: Partial<State>) {
this.state = { ...this.state, ...partialState };
}
onInput({ value }: { value: number }) {
this.setState({ on: value > 0 }); // error: Argument of type '{ on: boolean; }' is not assignable to parameter of type 'Partial<State>'
}
}
最も参考になるコメント
これを書くとどうなるか考えてみてください