Typescript: НСвозмоТно ΠΏΡ€ΠΈΡΠ²ΠΎΠΈΡ‚ΡŒ совмСстимоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΌΡƒ свойству с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ `extends` Π² ΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½ΠΎΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ.

Π‘ΠΎΠ·Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π° 7 Π°ΠΏΡ€. 2017  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ  Β·  Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: microsoft/TypeScript

ВСрсия 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

ВсС 3 ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

ΠŸΠΎΠ΄ΡƒΠΌΠ°ΠΉΡ‚Π΅, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚, Ссли Π²Ρ‹ Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ это

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`.

ЛогичСски ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π½Π° это ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ

Π£Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅

  1. ΠŸΡƒΡΡ‚ΡŒ P Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚ΠΈΠΏΠΎΠΌ { on: boolean }
  2. Для всСх Ρ‚ΠΈΠΏΠΎΠ² T Ρ‚Π°ΠΊΠΈΡ… Ρ‡Ρ‚ΠΎ T присваиваСтся P , ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Stateful<T> ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠ΅ Π²Ρ‹ΡˆΠ΅, Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ.

ΠžΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΆΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½Ρ‚Ρ€ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠΌ

  1. ΠŸΡƒΡΡ‚ΡŒ U Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚ΠΈΠΏΠΎΠΌ { on: boolean, value: number }
  2. U назначаСтся P -> ΠΏΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΡŽ
  3. Stateful<U> Π½Π΅Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ -> ΠΏΡƒΡ‚Π΅ΠΌ подстановки
  4. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, сущСствуСт Ρ‚ΠΈΠΏ 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>'
    }
}
Π‘Ρ‹Π»Π° Π»ΠΈ эта страница ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ?
0 / 5 - 0 Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³ΠΈ