ΠΠ΅ΡΡΠΈΡ 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
. Π― ΠΎΠΆΠΈΠ΄Π°Ρ ΡΠ°ΠΊΠΎΠ³ΠΎ ΠΆΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΡ ΠΎΡ ΠΊΠ»Π°ΡΡΠ° GenericComponent
ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ±ΡΠΈΠΉ State
ΡΠ²Π½ΠΎ ΡΠ°ΡΡΠΈΡΡΠ΅Ρ BaseState
.
Π€Π°ΠΊΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅:
ΠΠΌΠ΅ΡΡΠΎ ΡΡΠΎΠ³ΠΎ Ρ ΠΏΠΎΠ»ΡΡΠ°Ρ ΡΠ»Π΅Π΄ΡΡΡΡΡ ΠΎΡΠΈΠ±ΠΊΡ, ΡΠ²ΡΠ·Π°Π½Π½ΡΡ Ρ 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,
Stateful
ΠΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈ ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ Π½Π° ΡΡΠΎ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ
Π£ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠ΅
P
Π±ΡΠ΄Π΅Ρ ΡΠΈΠΏΠΎΠΌ { on: boolean }
T
ΡΠ°ΠΊΠΈΡ
ΡΡΠΎ T
ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°Π΅ΡΡΡ P
, ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Stateful<T>
ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠ΅ Π²ΡΡΠ΅, Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ.ΠΠΏΡΠΎΠ²Π΅ΡΠΆΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΡΠΏΡΠΈΠΌΠ΅ΡΠΎΠΌ
U
Π±ΡΠ΄Π΅Ρ ΡΠΈΠΏΠΎΠΌ { on: boolean, value: number }
U
Π½Π°Π·Π½Π°ΡΠ°Π΅ΡΡΡ P
-> ΠΏΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡStateful<U>
Π½Π΅Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ -> ΠΏΡΡΠ΅ΠΌ ΠΏΠΎΠ΄ΡΡΠ°Π½ΠΎΠ²ΠΊΠΈT
ΡΠ°ΠΊΠΎΠΉ, ΡΡΠΎ T
ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°Π΅ΡΡΡ P
Π° Stateful<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>'
}
}
Π‘Π°ΠΌΡΠΉ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ
ΠΠΎΠ΄ΡΠΌΠ°ΠΉΡΠ΅, ΡΡΠΎ ΠΏΡΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ, Π΅ΡΠ»ΠΈ Π²Ρ Π½Π°ΠΏΠΈΡΠ΅ΡΠ΅ ΡΡΠΎ